memorix 1.7.3 → 1.8.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/CHANGELOG.md +32 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/cli/index.js +1407 -192
- package/dist/dashboard/static/app.js +88 -4
- package/dist/dashboard/static/index.html +10 -0
- package/dist/dashboard/static/style.css +86 -0
- package/dist/index.js +875 -164
- package/dist/maintenance-runner.js +607 -68
- package/dist/media-audio-runner.js +602 -63
- package/dist/media-video-runner.js +607 -68
- package/dist/memcode-runtime/CHANGELOG.md +32 -0
- package/dist/sdk.js +874 -163
- package/dist/types.d.ts +8 -0
- package/dist/vector-backfill-runner.js +607 -68
- package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
- package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +75 -0
- package/docs/API_REFERENCE.md +37 -1
- package/docs/DASHBOARD.md +10 -0
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/README.md +11 -1
- package/package.json +1 -1
- package/plugins/antigravity/memorix/rules/memorix.md +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/memorix/SKILL.md +1 -1
- package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/gemini/memorix/GEMINI.md +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/plugins/pi/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/server.json +2 -2
- package/src/cli/capability-map.ts +2 -0
- package/src/cli/commands/context.ts +11 -0
- package/src/cli/commands/evidence.ts +56 -0
- package/src/cli/commands/feedback.ts +58 -0
- package/src/cli/commands/resume.ts +2 -0
- package/src/cli/commands/serve-http.ts +201 -12
- package/src/cli/fallback-budget.ts +59 -0
- package/src/cli/index.ts +5 -1
- package/src/compact/engine.ts +26 -1
- package/src/config/dotenv-loader.ts +17 -0
- package/src/dashboard/config-provenance.ts +17 -0
- package/src/dashboard/evidence.ts +63 -0
- package/src/dashboard/server.ts +93 -68
- package/src/dashboard/static/index.html +10 -0
- package/src/dashboard/static/style.css +86 -0
- package/src/hooks/installers/index.ts +1 -1
- package/src/hooks/official-skills.ts +3 -3
- package/src/hooks/rules/memorix-agent-rules.md +1 -1
- package/src/memory/feedback-model.ts +4 -0
- package/src/memory/feedback.ts +220 -0
- package/src/memory/observations.ts +19 -0
- package/src/memory/retention.ts +38 -5
- package/src/server/mcp-binding-store.ts +79 -0
- package/src/server/mcp-diagnostics.ts +40 -0
- package/src/server/tool-profile.ts +4 -0
- package/src/server.ts +121 -1
- package/src/store/evidence-store.ts +261 -0
- package/src/store/sqlite-db.ts +104 -0
- package/src/types.ts +8 -0
package/src/dashboard/server.ts
CHANGED
|
@@ -22,10 +22,13 @@ import { loadDotenv } from '../config/dotenv-loader.js';
|
|
|
22
22
|
import { resetDotenv } from '../config/dotenv-loader.js';
|
|
23
23
|
import { initProjectRoot } from '../config/yaml-loader.js';
|
|
24
24
|
import { clearProjectRoot } from '../config/yaml-loader.js';
|
|
25
|
+
import { getResolvedConfig } from '../config/resolved-config.js';
|
|
25
26
|
import { scopeKnowledgeGraphToProject } from '../memory/graph-scope.js';
|
|
26
27
|
import { projectObservationRetention, summarizeRetentionProjections } from '../memory/retention.js';
|
|
27
28
|
import { canManageObservation, filterReadableObservations } from '../memory/visibility.js';
|
|
28
29
|
import type { Observation } from '../types.js';
|
|
30
|
+
import { EvidenceCardStore } from '../store/evidence-store.js';
|
|
31
|
+
import { MemoryFeedbackStore } from '../memory/feedback.js';
|
|
29
32
|
import {
|
|
30
33
|
DashboardMaintenanceError,
|
|
31
34
|
executeCleanup,
|
|
@@ -37,6 +40,7 @@ import {
|
|
|
37
40
|
previewDeduplicate,
|
|
38
41
|
previewRetentionArchive,
|
|
39
42
|
} from './maintenance.js';
|
|
43
|
+
import { resolveDashboardKeySource } from './config-provenance.js';
|
|
40
44
|
|
|
41
45
|
// MIME types for static file serving
|
|
42
46
|
const MIME_TYPES: Record<string, string> = {
|
|
@@ -326,6 +330,22 @@ async function handleApi(
|
|
|
326
330
|
break;
|
|
327
331
|
}
|
|
328
332
|
|
|
333
|
+
case '/evidence': {
|
|
334
|
+
const observations = filterDashboardObservations(
|
|
335
|
+
await getObservationStore().loadByProject(effectiveProjectId, { status: 'active' }),
|
|
336
|
+
effectiveProjectId,
|
|
337
|
+
);
|
|
338
|
+
const evidenceStore = new EvidenceCardStore();
|
|
339
|
+
await evidenceStore.init(effectiveDataDir);
|
|
340
|
+
evidenceStore.syncObservations(observations);
|
|
341
|
+
const query = url.searchParams.get('q') || '';
|
|
342
|
+
const limit = Number(url.searchParams.get('limit') || 20);
|
|
343
|
+
const cards = evidenceStore.list(effectiveProjectId, { limit: Math.min(100, Math.max(1, limit)) })
|
|
344
|
+
.filter((card) => !query || [card.title, card.summary, card.sourceRef, card.locator ?? ''].join(' ').toLowerCase().includes(query.toLowerCase()));
|
|
345
|
+
sendJson(res, { cards, projectId: effectiveProjectId });
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
|
|
329
349
|
case '/sessions': {
|
|
330
350
|
const allSessions = await getSessionStore().loadAll();
|
|
331
351
|
const sessions = filterByProject(allSessions as Array<{ projectId?: string }>, effectiveProjectId);
|
|
@@ -381,10 +401,15 @@ async function handleApi(
|
|
|
381
401
|
}));
|
|
382
402
|
|
|
383
403
|
const retentionReferenceTime = new Date(now);
|
|
404
|
+
const feedback = new MemoryFeedbackStore();
|
|
405
|
+
await feedback.init(effectiveDataDir).catch(() => undefined);
|
|
384
406
|
const retention = summarizeRetentionProjections(
|
|
385
407
|
observations
|
|
386
408
|
.filter((observation) => observation.type !== 'probe')
|
|
387
|
-
.map((observation) => projectObservationRetention(observation, {
|
|
409
|
+
.map((observation) => projectObservationRetention(observation, {
|
|
410
|
+
referenceTime: retentionReferenceTime,
|
|
411
|
+
feedback: feedback.getState(effectiveProjectId, 'observation', String(observation.id)),
|
|
412
|
+
})),
|
|
388
413
|
);
|
|
389
414
|
const retentionSummary = {
|
|
390
415
|
active: retention.active,
|
|
@@ -489,11 +514,16 @@ async function handleApi(
|
|
|
489
514
|
);
|
|
490
515
|
|
|
491
516
|
const referenceTime = new Date();
|
|
517
|
+
const feedback = new MemoryFeedbackStore();
|
|
518
|
+
await feedback.init(effectiveDataDir).catch(() => undefined);
|
|
492
519
|
const rows = observations
|
|
493
520
|
.filter((observation) => observation.type !== 'probe')
|
|
494
521
|
.map((observation) => ({
|
|
495
522
|
observation,
|
|
496
|
-
retention: projectObservationRetention(observation, {
|
|
523
|
+
retention: projectObservationRetention(observation, {
|
|
524
|
+
referenceTime,
|
|
525
|
+
feedback: feedback.getState(effectiveProjectId, 'observation', String(observation.id)),
|
|
526
|
+
}),
|
|
497
527
|
}))
|
|
498
528
|
.sort((a, b) => b.retention.displayScore - a.retention.displayScore);
|
|
499
529
|
const summary = summarizeRetentionProjections(rows.map((row) => row.retention));
|
|
@@ -580,26 +610,18 @@ async function handleApi(
|
|
|
580
610
|
const { existsSync } = await import('node:fs');
|
|
581
611
|
const { join } = await import('node:path');
|
|
582
612
|
|
|
583
|
-
let yml: any = {};
|
|
584
613
|
// Use the real project root from dashboard state, not process.cwd()
|
|
585
614
|
const configProjectRoot = effectiveProjectRoot;
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
} catch { /* best effort */ }
|
|
590
|
-
|
|
591
|
-
// Load .env files so process.env reflects actual config (fixes #74, #62)
|
|
592
|
-
if (configProjectRoot) {
|
|
593
|
-
try {
|
|
594
|
-
const { loadDotenv } = await import('../config/dotenv-loader.js');
|
|
595
|
-
loadDotenv(configProjectRoot);
|
|
596
|
-
} catch { /* best effort */ }
|
|
597
|
-
}
|
|
615
|
+
// This is the same TOML-first chain used by status and runtime lanes.
|
|
616
|
+
// Do not fall back to user config if a bound project cannot resolve.
|
|
617
|
+
const resolved = getResolvedConfig({ projectRoot: configProjectRoot });
|
|
598
618
|
|
|
599
619
|
// Check which config files exist
|
|
600
620
|
const files: Record<string, { exists: boolean; path: string; unavailable?: boolean }> = {
|
|
601
621
|
'project memorix.yml': { exists: false, path: '', unavailable: !configProjectRoot },
|
|
602
622
|
'user memorix.yml': { exists: false, path: '' },
|
|
623
|
+
'project memorix.toml': { exists: false, path: '', unavailable: !configProjectRoot },
|
|
624
|
+
'user config.toml': { exists: false, path: '' },
|
|
603
625
|
'project .env': { exists: false, path: '', unavailable: !configProjectRoot },
|
|
604
626
|
'user .env': { exists: false, path: '' },
|
|
605
627
|
'legacy config.json': { exists: false, path: '' },
|
|
@@ -609,6 +631,8 @@ async function handleApi(
|
|
|
609
631
|
const paths: Record<string, string | null> = {
|
|
610
632
|
'project memorix.yml': configProjectRoot ? join(configProjectRoot, 'memorix.yml') : null,
|
|
611
633
|
'user memorix.yml': join(home, '.memorix', 'memorix.yml'),
|
|
634
|
+
'project memorix.toml': configProjectRoot ? join(configProjectRoot, 'memorix.toml') : null,
|
|
635
|
+
'user config.toml': join(home, '.memorix', 'config.toml'),
|
|
612
636
|
'project .env': configProjectRoot ? join(configProjectRoot, '.env') : null,
|
|
613
637
|
'user .env': join(home, '.memorix', '.env'),
|
|
614
638
|
'legacy config.json': join(home, '.memorix', 'config.json'),
|
|
@@ -626,82 +650,83 @@ async function handleApi(
|
|
|
626
650
|
const values: Array<{ key: string; value: string; source: string; sensitive?: boolean }> = [];
|
|
627
651
|
|
|
628
652
|
// LLM
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
};
|
|
653
|
+
const tomlSource = configProjectRoot && files['project memorix.toml'].exists
|
|
654
|
+
? 'memorix.toml'
|
|
655
|
+
: files['user config.toml'].exists ? 'config.toml' : 'default';
|
|
656
|
+
const legacySource = files['project memorix.yml'].exists || files['user memorix.yml'].exists
|
|
657
|
+
? 'memorix.yml'
|
|
658
|
+
: files['legacy config.json'].exists ? 'config.json' : 'default';
|
|
659
|
+
const configSource = resolved.sources.toml.length > 0 ? tomlSource
|
|
660
|
+
: resolved.sources.legacy.length > 0 ? legacySource : 'default';
|
|
661
|
+
const source = (envKey: string): string => resolveDashboardKeySource({
|
|
662
|
+
value: process.env[envKey] ?? '',
|
|
663
|
+
envKeys: [envKey],
|
|
664
|
+
configSource,
|
|
665
|
+
});
|
|
642
666
|
|
|
643
|
-
|
|
644
|
-
if (llmProvider) values.push({ key: 'llm.provider', value: llmProvider, source: await getEnvSource('MEMORIX_LLM_PROVIDER', yml.llm?.provider ? 'memorix.yml' : undefined) });
|
|
667
|
+
if (resolved.memory.llm.provider) values.push({ key: 'llm.provider', value: resolved.memory.llm.provider, source: source('MEMORIX_LLM_PROVIDER') });
|
|
645
668
|
|
|
646
|
-
|
|
647
|
-
if (llmModel) values.push({ key: 'llm.model', value: llmModel, source: await getEnvSource('MEMORIX_LLM_MODEL', yml.llm?.model ? 'memorix.yml' : undefined) });
|
|
669
|
+
if (resolved.memory.llm.model) values.push({ key: 'llm.model', value: resolved.memory.llm.model, source: source('MEMORIX_LLM_MODEL') });
|
|
648
670
|
|
|
649
|
-
const llmKey =
|
|
671
|
+
const llmKey = resolved.memory.llm.apiKey;
|
|
672
|
+
const memoryKeyEnv = [
|
|
673
|
+
'MEMORIX_LLM_API_KEY',
|
|
674
|
+
'MEMORIX_API_KEY',
|
|
675
|
+
'OPENAI_API_KEY',
|
|
676
|
+
'ANTHROPIC_API_KEY',
|
|
677
|
+
...(resolved.memory.llm.provider === 'openrouter' || resolved.memory.llm.baseUrl?.includes('openrouter.ai')
|
|
678
|
+
? ['OPENROUTER_API_KEY']
|
|
679
|
+
: []),
|
|
680
|
+
];
|
|
650
681
|
if (llmKey) {
|
|
651
|
-
|
|
652
|
-
if (process.env.MEMORIX_LLM_API_KEY) src = await getEnvSource('MEMORIX_LLM_API_KEY');
|
|
653
|
-
else if (process.env.MEMORIX_API_KEY) src = await getEnvSource('MEMORIX_API_KEY');
|
|
654
|
-
else if (yml.llm?.apiKey) src = 'memorix.yml (move to .env!)';
|
|
655
|
-
else if (process.env.OPENAI_API_KEY) src = await getEnvSource('OPENAI_API_KEY');
|
|
682
|
+
const src = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
|
|
656
683
|
values.push({ key: 'llm.apiKey', value: '****' + llmKey.slice(-4), source: src, sensitive: true });
|
|
657
684
|
} else {
|
|
658
685
|
values.push({ key: 'llm.apiKey', value: 'not set', source: 'none' });
|
|
659
686
|
}
|
|
660
687
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
let source: string;
|
|
664
|
-
if (process.env.MEMORIX_AGENT_PROVIDER) source = await getEnvSource('MEMORIX_AGENT_PROVIDER');
|
|
665
|
-
else if (process.env.MEMORIX_AGENT_LLM_PROVIDER) source = `${await getEnvSource('MEMORIX_AGENT_LLM_PROVIDER')} (legacy)`;
|
|
666
|
-
else source = yml.agent?.provider ? 'memorix.yml' : 'default';
|
|
667
|
-
values.push({ key: 'agent.provider', value: agentProvider, source });
|
|
688
|
+
if (resolved.agent.provider) {
|
|
689
|
+
values.push({ key: 'agent.provider', value: resolved.agent.provider, source: source('MEMORIX_AGENT_PROVIDER') });
|
|
668
690
|
}
|
|
669
691
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
let source: string;
|
|
673
|
-
if (process.env.MEMORIX_AGENT_MODEL) source = await getEnvSource('MEMORIX_AGENT_MODEL');
|
|
674
|
-
else if (process.env.MEMORIX_AGENT_LLM_MODEL) source = `${await getEnvSource('MEMORIX_AGENT_LLM_MODEL')} (legacy)`;
|
|
675
|
-
else source = yml.agent?.model ? 'memorix.yml' : 'default';
|
|
676
|
-
values.push({ key: 'agent.model', value: agentModel, source });
|
|
692
|
+
if (resolved.agent.model) {
|
|
693
|
+
values.push({ key: 'agent.model', value: resolved.agent.model, source: source('MEMORIX_AGENT_MODEL') });
|
|
677
694
|
}
|
|
678
695
|
|
|
679
|
-
const agentKey =
|
|
696
|
+
const agentKey = resolved.agent.apiKey;
|
|
680
697
|
if (agentKey) {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
698
|
+
const src = resolveDashboardKeySource({
|
|
699
|
+
value: agentKey,
|
|
700
|
+
envKeys: ['MEMORIX_AGENT_API_KEY', 'MEMORIX_AGENT_LLM_API_KEY'],
|
|
701
|
+
configSource,
|
|
702
|
+
});
|
|
685
703
|
values.push({ key: 'agent.apiKey', value: '****' + agentKey.slice(-4), source: src, sensitive: true });
|
|
686
704
|
} else {
|
|
687
|
-
values.push({
|
|
705
|
+
values.push({
|
|
706
|
+
key: 'agent.apiKey',
|
|
707
|
+
value: 'fallback to llm.apiKey',
|
|
708
|
+
source: llmKey
|
|
709
|
+
? resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource })
|
|
710
|
+
: 'default',
|
|
711
|
+
});
|
|
688
712
|
}
|
|
689
713
|
|
|
690
714
|
// Embedding
|
|
691
|
-
|
|
692
|
-
values.push({ key: 'embedding.
|
|
715
|
+
values.push({ key: 'embedding.provider', value: resolved.embedding.provider || 'off', source: source('MEMORIX_EMBEDDING') });
|
|
716
|
+
if (resolved.embedding.model) values.push({ key: 'embedding.model', value: resolved.embedding.model, source: source('MEMORIX_EMBEDDING_MODEL') });
|
|
693
717
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
718
|
+
if (resolved.rerank.provider !== 'off') {
|
|
719
|
+
values.push({ key: 'rerank.provider', value: resolved.rerank.provider, source: source('MEMORIX_RERANK_PROVIDER') });
|
|
720
|
+
if (resolved.rerank.model) values.push({ key: 'rerank.model', value: resolved.rerank.model, source: source('MEMORIX_RERANK_MODEL') });
|
|
721
|
+
}
|
|
697
722
|
|
|
698
|
-
//
|
|
699
|
-
|
|
700
|
-
|
|
723
|
+
// Git
|
|
724
|
+
values.push({ key: 'git.autoHook', value: String(resolved.git.autoHook ?? false), source: configSource });
|
|
725
|
+
values.push({ key: 'git.skipMergeCommits', value: String(resolved.git.skipMergeCommits ?? true), source: configSource });
|
|
701
726
|
|
|
702
727
|
// Server
|
|
703
|
-
values.push({ key: 'server.transport', value:
|
|
704
|
-
values.push({ key: 'server.dashboard', value: String(
|
|
728
|
+
values.push({ key: 'server.transport', value: resolved.server.transport || 'stdio', source: configSource });
|
|
729
|
+
values.push({ key: 'server.dashboard', value: String(resolved.server.dashboard ?? true), source: configSource });
|
|
705
730
|
|
|
706
731
|
sendJson(res, { files, values });
|
|
707
732
|
break;
|
|
@@ -92,6 +92,15 @@
|
|
|
92
92
|
</svg>
|
|
93
93
|
<span class="nav-label">Observations</span>
|
|
94
94
|
</button>
|
|
95
|
+
<button class="nav-btn" data-page="evidence" title="Evidence" aria-label="Evidence">
|
|
96
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
97
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
98
|
+
<polyline points="14 2 14 8 20 8"/>
|
|
99
|
+
<line x1="8" y1="13" x2="16" y2="13"/>
|
|
100
|
+
<line x1="8" y1="17" x2="14" y2="17"/>
|
|
101
|
+
</svg>
|
|
102
|
+
<span class="nav-label">Evidence</span>
|
|
103
|
+
</button>
|
|
95
104
|
</div>
|
|
96
105
|
<div class="sidebar-section-label" data-section="health">HEALTH</div>
|
|
97
106
|
<div class="sidebar-nav">
|
|
@@ -175,6 +184,7 @@
|
|
|
175
184
|
<div id="page-knowledge" class="page"></div>
|
|
176
185
|
<div id="page-graph" class="page"></div>
|
|
177
186
|
<div id="page-observations" class="page"></div>
|
|
187
|
+
<div id="page-evidence" class="page"></div>
|
|
178
188
|
<div id="page-retention" class="page"></div>
|
|
179
189
|
<div id="page-config" class="page"></div>
|
|
180
190
|
<div id="page-identity" class="page"></div>
|
|
@@ -64,6 +64,92 @@
|
|
|
64
64
|
--transition-emphasized: 500ms cubic-bezier(0.2, 0, 0, 1);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/* Evidence Console: provenance is readable at a glance and stays bounded on
|
|
68
|
+
narrow screens; long paths and generated titles never widen the viewport. */
|
|
69
|
+
.evidence-console {
|
|
70
|
+
display: grid;
|
|
71
|
+
gap: 12px;
|
|
72
|
+
min-width: 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.evidence-card {
|
|
76
|
+
border: 1px solid var(--border-color, rgba(148, 163, 184, .18));
|
|
77
|
+
border-radius: 8px;
|
|
78
|
+
background: var(--surface, rgba(15, 23, 42, .45));
|
|
79
|
+
padding: 16px;
|
|
80
|
+
min-width: 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.evidence-card-header {
|
|
84
|
+
display: flex;
|
|
85
|
+
gap: 12px;
|
|
86
|
+
align-items: flex-start;
|
|
87
|
+
justify-content: space-between;
|
|
88
|
+
min-width: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.evidence-card-heading {
|
|
92
|
+
min-width: 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.evidence-card-heading h2 {
|
|
96
|
+
margin: 4px 0 0;
|
|
97
|
+
font-size: 16px;
|
|
98
|
+
line-height: 1.35;
|
|
99
|
+
overflow-wrap: anywhere;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.evidence-card-kind {
|
|
103
|
+
color: var(--text-muted);
|
|
104
|
+
font-size: 11px;
|
|
105
|
+
text-transform: uppercase;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.evidence-card-state {
|
|
109
|
+
display: flex;
|
|
110
|
+
gap: 6px;
|
|
111
|
+
flex: 0 0 auto;
|
|
112
|
+
flex-wrap: wrap;
|
|
113
|
+
justify-content: flex-end;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.evidence-state {
|
|
117
|
+
border: 1px solid currentColor;
|
|
118
|
+
border-radius: 999px;
|
|
119
|
+
padding: 3px 7px;
|
|
120
|
+
font-size: 11px;
|
|
121
|
+
white-space: nowrap;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.evidence-current, .evidence-verified { color: #4ade80; }
|
|
125
|
+
.evidence-stale, .evidence-conflicted { color: #fb923c; }
|
|
126
|
+
.evidence-unverified { color: var(--text-muted); }
|
|
127
|
+
|
|
128
|
+
.evidence-card-summary {
|
|
129
|
+
margin: 12px 0;
|
|
130
|
+
color: var(--text-secondary, var(--text-muted));
|
|
131
|
+
line-height: 1.55;
|
|
132
|
+
overflow-wrap: anywhere;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.evidence-card-meta {
|
|
136
|
+
display: grid;
|
|
137
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
138
|
+
gap: 10px;
|
|
139
|
+
margin: 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.evidence-card-meta div { min-width: 0; }
|
|
143
|
+
.evidence-card-meta dt { color: var(--text-muted); font-size: 11px; margin-bottom: 3px; }
|
|
144
|
+
.evidence-card-meta dd { margin: 0; font-size: 12px; overflow-wrap: anywhere; }
|
|
145
|
+
.evidence-card-warning { margin-top: 10px; color: #fb923c; font-size: 12px; overflow-wrap: anywhere; }
|
|
146
|
+
|
|
147
|
+
@media (max-width: 600px) {
|
|
148
|
+
.evidence-card-header { display: block; }
|
|
149
|
+
.evidence-card-state { justify-content: flex-start; margin-top: 10px; }
|
|
150
|
+
.evidence-card-meta { grid-template-columns: 1fr; }
|
|
151
|
+
}
|
|
152
|
+
|
|
67
153
|
/* Light Theme - MD3 */
|
|
68
154
|
[data-theme="light"] {
|
|
69
155
|
--bg-base: #FFFBFE;
|
|
@@ -1259,7 +1259,7 @@ function getAgentRulesContent(agent?: AgentName, scope: 'project' | 'global' = '
|
|
|
1259
1259
|
'',
|
|
1260
1260
|
`Default first step for non-trivial coding work: call \x60memorix_project_context\x60 with the user's actual task before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Memorix will choose a task-lensed brief (bugfix, feature, release, onboarding, refactor, docs, test, or general). When the task is continuing prior work, the same brief also includes a bounded prior-work projection. Treat its "Start here" files as the first ${contextNoun} files to inspect.`,
|
|
1261
1261
|
'',
|
|
1262
|
-
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select \x60memorix_project_context\x60 first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: \x60memorix resume "<task>" --brief-json\x60. For a new task, use \x60memorix context "<task>" --brief-json\x60 instead. The absence of \x60.memorix\x60 or visible memory files never proves project memory is empty. Use \x60--json\x60 only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
1262
|
+
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select \x60memorix_project_context\x60 first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: \x60memorix resume "<task>" --fallback --brief-json\x60. For a new task, use \x60memorix context "<task>" --fallback --brief-json\x60 instead. The absence of \x60.memorix\x60 or visible memory files never proves project memory is empty. Use \x60--json\x60 only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
1263
1263
|
'',
|
|
1264
1264
|
'After a successful \x60memorix_project_context\x60 result, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use \x60memorix_context_pack\x60, \x60memorix_search\x60, or \x60memorix_detail\x60 only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in \x60purpose\x60 when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.',
|
|
1265
1265
|
'If the user asks for read-only work or says not to modify files, do not call \x60memorix_store\x60 just to record an assessment. Store only when the user explicitly asks to preserve it.',
|
|
@@ -31,8 +31,8 @@ export const OFFICIAL_MEMORIX_SKILLS: OfficialMemorixSkill[] = [
|
|
|
31
31
|
'',
|
|
32
32
|
'| Situation | Prefer | CLI fallback |',
|
|
33
33
|
'|---|---|---|',
|
|
34
|
-
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --brief-json` |',
|
|
35
|
-
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --brief-json` |',
|
|
34
|
+
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --fallback --brief-json` |',
|
|
35
|
+
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --fallback --brief-json` |',
|
|
36
36
|
'| Need structured refs/freshness for code-bound memories | `memorix_context_pack` | `memorix codegraph context-pack --task "<topic>"` |',
|
|
37
37
|
'| Explicit memory graph question | `memorix_graph_context` | `memorix memory graph-context --query "<topic>"` |',
|
|
38
38
|
'| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
|
|
@@ -45,7 +45,7 @@ export const OFFICIAL_MEMORIX_SKILLS: OfficialMemorixSkill[] = [
|
|
|
45
45
|
'',
|
|
46
46
|
'- Default first step for non-trivial coding work: call `memorix_project_context` before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Pass the user\'s actual task so Memorix can choose a bugfix, feature, release, onboarding, refactor, docs, test, or general brief. Start by reading its suggested files.',
|
|
47
47
|
'- In Claude Code headless/print-mode, an initial MCP `pending` status is not a failure by itself. Prefer MCP first: use the client\'s tool discovery/dynamic loading to find `memorix_project_context` when it is not in the first visible tool list.',
|
|
48
|
-
'- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --brief-json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --brief-json` instead. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
|
|
48
|
+
'- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --fallback --brief-json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --fallback --brief-json` instead. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
|
|
49
49
|
'- After a successful `memorix_project_context`, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use Context Pack, search, or detail only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.',
|
|
50
50
|
'- If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.',
|
|
51
51
|
'- Use `memorix_search` for a specific decision, bug, file, or prior change that the project context did not answer. Fetch detail only for a result you still need after the brief.',
|
|
@@ -7,7 +7,7 @@ You have access to Memorix memory tools. Follow these rules to maintain persiste
|
|
|
7
7
|
At the beginning of non-trivial coding work, use Memorix Memory Autopilot before local progress notes or broad file exploration. A session bind is not required for every conversation.
|
|
8
8
|
|
|
9
9
|
1. Default first step for non-trivial coding work: call `memorix_project_context` with the user's actual task before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Memorix will choose a task-lensed brief (bugfix, feature, release, onboarding, refactor, docs, test, or general). Treat its "Start here" files as the first code or docs to inspect.
|
|
10
|
-
2. If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user's real task before inspecting files, Git history, progress notes, or guessing: use `memorix resume "<task>" --brief-json`. For a new task, use `memorix context "<task>" --brief-json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax. Use `--json` only when a diagnostic needs the detailed legacy payload.
|
|
10
|
+
2. If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user's real task before inspecting files, Git history, progress notes, or guessing: use `memorix resume "<task>" --fallback --brief-json`. For a new task, use `memorix context "<task>" --fallback --brief-json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax. Use `--json` only when a diagnostic needs the detailed legacy payload.
|
|
11
11
|
3. After a successful `memorix_project_context` result, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use `memorix_context_pack`, `memorix_search`, or `memorix_detail` only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.
|
|
12
12
|
If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.
|
|
13
13
|
4. Use `memorix_context_pack` when you need structured refs and freshness for code-bound memories.
|