memorix 1.1.7 → 1.1.8
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 +13 -0
- package/CLAUDE.md +6 -1
- package/README.md +21 -0
- package/README.zh-CN.md +21 -0
- package/TEAM.md +86 -86
- package/dist/cli/index.js +730 -150
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/static/index.html +201 -201
- package/dist/dashboard/static/style.css +3584 -3584
- package/dist/index.js +15 -8
- package/dist/index.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +13 -0
- package/dist/memcode-runtime/package.json +4 -4
- package/dist/sdk.js +15 -8
- package/dist/sdk.js.map +1 -1
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +18 -0
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/docs/SETUP.md +10 -0
- package/docs/dev-log/progress.txt +35 -26
- package/package.json +1 -1
- package/src/audit/index.ts +156 -156
- package/src/cli/commands/agent-integrations.ts +623 -0
- package/src/cli/commands/audit-list.ts +89 -89
- package/src/cli/commands/background.ts +659 -659
- package/src/cli/commands/cleanup.ts +255 -255
- package/src/cli/commands/doctor.ts +23 -0
- package/src/cli/commands/formation.ts +48 -48
- package/src/cli/commands/git-hook-install.ts +111 -111
- package/src/cli/commands/handoff.ts +66 -66
- package/src/cli/commands/hooks-status.ts +63 -63
- package/src/cli/commands/ingest-commit.ts +153 -153
- package/src/cli/commands/ingest-image.ts +73 -73
- package/src/cli/commands/ingest-log.ts +180 -180
- package/src/cli/commands/ingest.ts +44 -44
- package/src/cli/commands/integrate-shared.ts +15 -15
- package/src/cli/commands/lock.ts +96 -96
- package/src/cli/commands/message.ts +121 -121
- package/src/cli/commands/poll.ts +70 -70
- package/src/cli/commands/purge-all-memory.ts +85 -85
- package/src/cli/commands/purge-project-memory.ts +83 -83
- package/src/cli/commands/reasoning.ts +132 -132
- package/src/cli/commands/repair.ts +60 -0
- package/src/cli/commands/retention.ts +108 -108
- package/src/cli/commands/serve-shared.ts +118 -118
- package/src/cli/commands/setup.ts +3 -3
- package/src/cli/commands/skills.ts +123 -123
- package/src/cli/commands/task.ts +192 -192
- package/src/cli/commands/transfer.ts +73 -73
- package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
- package/src/cli/index.ts +3 -1
- package/src/cli/tui/ChatView.tsx +234 -234
- package/src/cli/tui/CommandBar.tsx +312 -312
- package/src/cli/tui/ContextRail.tsx +118 -118
- package/src/cli/tui/HeaderBar.tsx +72 -72
- package/src/cli/tui/LogoBanner.tsx +51 -51
- package/src/cli/tui/Panels.tsx +632 -632
- package/src/cli/tui/Sidebar.tsx +179 -179
- package/src/cli/tui/chat-service.ts +742 -742
- package/src/cli/tui/data.ts +547 -547
- package/src/cli/tui/index.ts +41 -41
- package/src/cli/tui/markdown-render.tsx +371 -371
- package/src/cli/tui/theme.ts +178 -178
- package/src/cli/tui/use-mouse.ts +157 -157
- package/src/cli/tui/useNavigation.ts +56 -56
- package/src/cli/update-checker.ts +211 -211
- package/src/cli/version.ts +7 -7
- package/src/cli/workbench.ts +1 -1
- package/src/codegraph/context-pack.ts +5 -1
- package/src/codegraph/lite-provider.ts +5 -1
- package/src/codegraph/project-context.ts +5 -1
- package/src/compact/token-budget.ts +74 -74
- package/src/config/behavior.ts +59 -59
- package/src/dashboard/project-classification.ts +64 -64
- package/src/dashboard/static/index.html +201 -201
- package/src/dashboard/static/style.css +3584 -3584
- package/src/embedding/fastembed-provider.ts +142 -142
- package/src/embedding/transformers-provider.ts +111 -111
- package/src/git/extractor.ts +209 -209
- package/src/git/hooks-path.ts +85 -85
- package/src/git/noise-filter.ts +210 -210
- package/src/hooks/installers/index.ts +4 -4
- package/src/hooks/official-skills.ts +1 -1
- package/src/hooks/pattern-detector.ts +173 -173
- package/src/hooks/rules/memorix-agent-rules.md +2 -2
- package/src/hooks/significance-filter.ts +250 -250
- package/src/llm/memory-manager.ts +328 -328
- package/src/llm/provider.ts +885 -885
- package/src/llm/quality.ts +248 -248
- package/src/memory/attribution-guard.ts +249 -249
- package/src/memory/auto-relations.ts +107 -107
- package/src/memory/consolidation.ts +302 -302
- package/src/memory/disclosure-policy.ts +141 -141
- package/src/memory/entity-extractor.ts +197 -197
- package/src/memory/formation/evaluate.ts +217 -217
- package/src/memory/formation/extract.ts +361 -361
- package/src/memory/formation/index.ts +417 -417
- package/src/memory/formation/resolve.ts +344 -344
- package/src/memory/formation/types.ts +315 -315
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph.ts +197 -197
- package/src/memory/refs.ts +94 -94
- package/src/memory/retention.ts +433 -433
- package/src/memory/secret-filter.ts +79 -79
- package/src/memory/session.ts +523 -523
- package/src/multimodal/image-loader.ts +143 -143
- package/src/orchestrate/adapters/claude-stream.ts +192 -192
- package/src/orchestrate/adapters/claude.ts +111 -111
- package/src/orchestrate/adapters/codex-stream.ts +134 -134
- package/src/orchestrate/adapters/codex.ts +41 -41
- package/src/orchestrate/adapters/gemini-stream.ts +166 -166
- package/src/orchestrate/adapters/gemini.ts +42 -42
- package/src/orchestrate/adapters/index.ts +73 -73
- package/src/orchestrate/adapters/opencode-stream.ts +143 -143
- package/src/orchestrate/adapters/opencode.ts +47 -47
- package/src/orchestrate/adapters/spawn-helper.ts +286 -286
- package/src/orchestrate/adapters/types.ts +77 -77
- package/src/orchestrate/capability-router.ts +284 -284
- package/src/orchestrate/context-compact.ts +188 -188
- package/src/orchestrate/cost-tracker.ts +219 -219
- package/src/orchestrate/error-recovery.ts +191 -191
- package/src/orchestrate/evidence.ts +140 -140
- package/src/orchestrate/ledger.ts +110 -110
- package/src/orchestrate/memorix-bridge.ts +380 -380
- package/src/orchestrate/output-budget.ts +80 -80
- package/src/orchestrate/permission.ts +152 -152
- package/src/orchestrate/pipeline-trace.ts +131 -131
- package/src/orchestrate/prompt-builder.ts +155 -155
- package/src/orchestrate/ring-buffer.ts +37 -37
- package/src/orchestrate/task-graph.ts +389 -389
- package/src/orchestrate/verify-gate.ts +219 -219
- package/src/orchestrate/worktree.ts +232 -232
- package/src/project/aliases.ts +374 -374
- package/src/project/detector.ts +268 -268
- package/src/rules/adapters/claude-code.ts +99 -99
- package/src/rules/adapters/codex.ts +97 -97
- package/src/rules/adapters/copilot.ts +124 -124
- package/src/rules/adapters/cursor.ts +114 -114
- package/src/rules/adapters/kiro.ts +126 -126
- package/src/rules/adapters/trae.ts +56 -56
- package/src/rules/adapters/windsurf.ts +83 -83
- package/src/rules/syncer.ts +235 -235
- package/src/sdk.ts +327 -327
- package/src/search/intent-detector.ts +289 -289
- package/src/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/skills/mini-skills.ts +386 -386
- package/src/store/chat-store.ts +119 -119
- package/src/store/file-lock.ts +100 -100
- package/src/store/graph-store.ts +249 -249
- package/src/store/mini-skill-store.ts +349 -349
- package/src/store/obs-store.ts +255 -255
- package/src/store/persistence-json.ts +212 -212
- package/src/store/persistence.ts +291 -291
- package/src/store/project-affinity.ts +195 -195
- package/src/store/session-store.ts +259 -259
- package/src/store/sqlite-store.ts +339 -339
- package/src/team/event-bus.ts +76 -76
- package/src/team/file-locks.ts +173 -173
- package/src/team/handoff.ts +167 -167
- package/src/team/messages.ts +203 -203
- package/src/team/poll.ts +132 -132
- package/src/team/tasks.ts +211 -211
- package/src/wiki/generator.ts +237 -237
- package/src/wiki/knowledge-graph.ts +334 -334
- package/src/wiki/types.ts +85 -85
- package/src/workspace/mcp-adapters/codex.ts +191 -191
- package/src/workspace/mcp-adapters/copilot.ts +105 -105
- package/src/workspace/mcp-adapters/cursor.ts +53 -53
- package/src/workspace/mcp-adapters/kiro.ts +64 -64
- package/src/workspace/mcp-adapters/opencode.ts +123 -123
- package/src/workspace/mcp-adapters/trae.ts +134 -134
- package/src/workspace/mcp-adapters/windsurf.ts +91 -91
- package/src/workspace/sanitizer.ts +60 -60
- package/src/workspace/workflow-sync.ts +131 -131
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI Command: memorix purge all-memory
|
|
3
|
-
*
|
|
4
|
-
* Delete ALL memories (dangerous operation).
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { defineCommand } from 'citty';
|
|
8
|
-
import * as p from '@clack/prompts';
|
|
9
|
-
|
|
10
|
-
export default defineCommand({
|
|
11
|
-
meta: {
|
|
12
|
-
name: 'all-memory',
|
|
13
|
-
description: 'Delete ALL memories (dangerous)',
|
|
14
|
-
},
|
|
15
|
-
args: {},
|
|
16
|
-
run: async ({}) => {
|
|
17
|
-
p.intro('[WARN] Purge All Memory');
|
|
18
|
-
|
|
19
|
-
// Show warning
|
|
20
|
-
console.log('');
|
|
21
|
-
console.log('[WARN] WARNING: This will delete ALL memories!');
|
|
22
|
-
console.log('');
|
|
23
|
-
console.log('This will remove:');
|
|
24
|
-
console.log(' - All observations from all projects');
|
|
25
|
-
console.log(' - All entities and relations');
|
|
26
|
-
console.log(' - All embeddings');
|
|
27
|
-
console.log('');
|
|
28
|
-
console.log('This action CANNOT be undone.');
|
|
29
|
-
console.log('');
|
|
30
|
-
console.log('Project artifacts (hook files) will be preserved.');
|
|
31
|
-
console.log('');
|
|
32
|
-
|
|
33
|
-
// First confirmation
|
|
34
|
-
const confirmed1 = await p.confirm({
|
|
35
|
-
message: 'Are you sure you want to delete ALL memories?',
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
if (p.isCancel(confirmed1) || !confirmed1) {
|
|
39
|
-
p.outro('Purge cancelled.');
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Second confirmation (type "DELETE" to confirm)
|
|
44
|
-
const confirmed2 = await p.text({
|
|
45
|
-
message: 'Type "DELETE" to confirm:',
|
|
46
|
-
validate: (value) => {
|
|
47
|
-
if (value !== 'DELETE') {
|
|
48
|
-
return 'Please type "DELETE" to confirm';
|
|
49
|
-
}
|
|
50
|
-
return undefined;
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
if (p.isCancel(confirmed2) || confirmed2 !== 'DELETE') {
|
|
55
|
-
p.outro('Purge cancelled.');
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Delete all memories
|
|
60
|
-
try {
|
|
61
|
-
const {
|
|
62
|
-
getAllObservations,
|
|
63
|
-
resolveObservations,
|
|
64
|
-
} = await import('../../memory/observations.js');
|
|
65
|
-
const { withFreshIndex } = await import('../../memory/freshness.js');
|
|
66
|
-
const observations = await withFreshIndex(() => getAllObservations());
|
|
67
|
-
const ids = observations.map((o) => o.id);
|
|
68
|
-
|
|
69
|
-
if (ids.length === 0) {
|
|
70
|
-
console.log('No observations found.');
|
|
71
|
-
p.outro('No memories to purge.');
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const result = await resolveObservations(ids, 'archived');
|
|
76
|
-
|
|
77
|
-
console.log(`[OK] Archived ${result.resolved.length} observations`);
|
|
78
|
-
|
|
79
|
-
p.outro(`All memory purged. ${result.resolved.length} observations archived.`);
|
|
80
|
-
} catch (err) {
|
|
81
|
-
console.error(`[ERROR] Failed to purge all memory: ${err}`);
|
|
82
|
-
p.outro('Purge failed.');
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: memorix purge all-memory
|
|
3
|
+
*
|
|
4
|
+
* Delete ALL memories (dangerous operation).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineCommand } from 'citty';
|
|
8
|
+
import * as p from '@clack/prompts';
|
|
9
|
+
|
|
10
|
+
export default defineCommand({
|
|
11
|
+
meta: {
|
|
12
|
+
name: 'all-memory',
|
|
13
|
+
description: 'Delete ALL memories (dangerous)',
|
|
14
|
+
},
|
|
15
|
+
args: {},
|
|
16
|
+
run: async ({}) => {
|
|
17
|
+
p.intro('[WARN] Purge All Memory');
|
|
18
|
+
|
|
19
|
+
// Show warning
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log('[WARN] WARNING: This will delete ALL memories!');
|
|
22
|
+
console.log('');
|
|
23
|
+
console.log('This will remove:');
|
|
24
|
+
console.log(' - All observations from all projects');
|
|
25
|
+
console.log(' - All entities and relations');
|
|
26
|
+
console.log(' - All embeddings');
|
|
27
|
+
console.log('');
|
|
28
|
+
console.log('This action CANNOT be undone.');
|
|
29
|
+
console.log('');
|
|
30
|
+
console.log('Project artifacts (hook files) will be preserved.');
|
|
31
|
+
console.log('');
|
|
32
|
+
|
|
33
|
+
// First confirmation
|
|
34
|
+
const confirmed1 = await p.confirm({
|
|
35
|
+
message: 'Are you sure you want to delete ALL memories?',
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (p.isCancel(confirmed1) || !confirmed1) {
|
|
39
|
+
p.outro('Purge cancelled.');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Second confirmation (type "DELETE" to confirm)
|
|
44
|
+
const confirmed2 = await p.text({
|
|
45
|
+
message: 'Type "DELETE" to confirm:',
|
|
46
|
+
validate: (value) => {
|
|
47
|
+
if (value !== 'DELETE') {
|
|
48
|
+
return 'Please type "DELETE" to confirm';
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (p.isCancel(confirmed2) || confirmed2 !== 'DELETE') {
|
|
55
|
+
p.outro('Purge cancelled.');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Delete all memories
|
|
60
|
+
try {
|
|
61
|
+
const {
|
|
62
|
+
getAllObservations,
|
|
63
|
+
resolveObservations,
|
|
64
|
+
} = await import('../../memory/observations.js');
|
|
65
|
+
const { withFreshIndex } = await import('../../memory/freshness.js');
|
|
66
|
+
const observations = await withFreshIndex(() => getAllObservations());
|
|
67
|
+
const ids = observations.map((o) => o.id);
|
|
68
|
+
|
|
69
|
+
if (ids.length === 0) {
|
|
70
|
+
console.log('No observations found.');
|
|
71
|
+
p.outro('No memories to purge.');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const result = await resolveObservations(ids, 'archived');
|
|
76
|
+
|
|
77
|
+
console.log(`[OK] Archived ${result.resolved.length} observations`);
|
|
78
|
+
|
|
79
|
+
p.outro(`All memory purged. ${result.resolved.length} observations archived.`);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error(`[ERROR] Failed to purge all memory: ${err}`);
|
|
82
|
+
p.outro('Purge failed.');
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
});
|
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI Command: memorix purge project-memory
|
|
3
|
-
*
|
|
4
|
-
* Delete memories for the current project only.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { defineCommand } from 'citty';
|
|
8
|
-
import * as p from '@clack/prompts';
|
|
9
|
-
|
|
10
|
-
export default defineCommand({
|
|
11
|
-
meta: {
|
|
12
|
-
name: 'project-memory',
|
|
13
|
-
description: 'Delete memories for current project',
|
|
14
|
-
},
|
|
15
|
-
args: {},
|
|
16
|
-
run: async ({}) => {
|
|
17
|
-
const os = await import('node:os');
|
|
18
|
-
let cwd: string;
|
|
19
|
-
try { cwd = process.cwd(); } catch { cwd = os.homedir(); }
|
|
20
|
-
|
|
21
|
-
p.intro('Purge Project Memory');
|
|
22
|
-
|
|
23
|
-
// Show what will be deleted
|
|
24
|
-
console.log('');
|
|
25
|
-
console.log('Will delete memories for:');
|
|
26
|
-
console.log(` Project: ${cwd}`);
|
|
27
|
-
console.log('');
|
|
28
|
-
console.log('This will remove all observations, entities, and relations');
|
|
29
|
-
console.log('associated with this project from the memory database.');
|
|
30
|
-
console.log('');
|
|
31
|
-
console.log('Project artifacts (hook files) will be preserved.');
|
|
32
|
-
console.log('');
|
|
33
|
-
|
|
34
|
-
// Confirm
|
|
35
|
-
const confirmed = await p.confirm({
|
|
36
|
-
message: 'Continue purge?',
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (p.isCancel(confirmed) || !confirmed) {
|
|
40
|
-
p.outro('Purge cancelled.');
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Get project ID
|
|
45
|
-
const projectId = getProjectId(cwd);
|
|
46
|
-
|
|
47
|
-
// Delete project memories
|
|
48
|
-
try {
|
|
49
|
-
const {
|
|
50
|
-
getProjectObservations,
|
|
51
|
-
resolveObservations,
|
|
52
|
-
} = await import('../../memory/observations.js');
|
|
53
|
-
const { withFreshIndex } = await import('../../memory/freshness.js');
|
|
54
|
-
const observations = await withFreshIndex(() => getProjectObservations(projectId));
|
|
55
|
-
const ids = observations.map((o) => o.id);
|
|
56
|
-
|
|
57
|
-
if (ids.length === 0) {
|
|
58
|
-
console.log('No observations found for this project.');
|
|
59
|
-
p.outro('No memories to purge.');
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const result = await resolveObservations(ids, 'archived');
|
|
64
|
-
|
|
65
|
-
console.log(`[OK] Archived ${result.resolved.length} observations for project`);
|
|
66
|
-
|
|
67
|
-
p.outro(`Project memory purged. ${result.resolved.length} observations archived.`);
|
|
68
|
-
} catch (err) {
|
|
69
|
-
console.error(`[ERROR] Failed to purge project memory: ${err}`);
|
|
70
|
-
p.outro('Purge failed.');
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
function getProjectId(projectRoot: string): string {
|
|
76
|
-
try {
|
|
77
|
-
const { detectProject } = require('../project/detector.js');
|
|
78
|
-
const project = detectProject(projectRoot);
|
|
79
|
-
if (project) return project.id;
|
|
80
|
-
} catch { /* fallback below */ }
|
|
81
|
-
const normalized = projectRoot.replace(/\\/g, '/');
|
|
82
|
-
return `untracked/${normalized}`;
|
|
83
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: memorix purge project-memory
|
|
3
|
+
*
|
|
4
|
+
* Delete memories for the current project only.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineCommand } from 'citty';
|
|
8
|
+
import * as p from '@clack/prompts';
|
|
9
|
+
|
|
10
|
+
export default defineCommand({
|
|
11
|
+
meta: {
|
|
12
|
+
name: 'project-memory',
|
|
13
|
+
description: 'Delete memories for current project',
|
|
14
|
+
},
|
|
15
|
+
args: {},
|
|
16
|
+
run: async ({}) => {
|
|
17
|
+
const os = await import('node:os');
|
|
18
|
+
let cwd: string;
|
|
19
|
+
try { cwd = process.cwd(); } catch { cwd = os.homedir(); }
|
|
20
|
+
|
|
21
|
+
p.intro('Purge Project Memory');
|
|
22
|
+
|
|
23
|
+
// Show what will be deleted
|
|
24
|
+
console.log('');
|
|
25
|
+
console.log('Will delete memories for:');
|
|
26
|
+
console.log(` Project: ${cwd}`);
|
|
27
|
+
console.log('');
|
|
28
|
+
console.log('This will remove all observations, entities, and relations');
|
|
29
|
+
console.log('associated with this project from the memory database.');
|
|
30
|
+
console.log('');
|
|
31
|
+
console.log('Project artifacts (hook files) will be preserved.');
|
|
32
|
+
console.log('');
|
|
33
|
+
|
|
34
|
+
// Confirm
|
|
35
|
+
const confirmed = await p.confirm({
|
|
36
|
+
message: 'Continue purge?',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (p.isCancel(confirmed) || !confirmed) {
|
|
40
|
+
p.outro('Purge cancelled.');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Get project ID
|
|
45
|
+
const projectId = getProjectId(cwd);
|
|
46
|
+
|
|
47
|
+
// Delete project memories
|
|
48
|
+
try {
|
|
49
|
+
const {
|
|
50
|
+
getProjectObservations,
|
|
51
|
+
resolveObservations,
|
|
52
|
+
} = await import('../../memory/observations.js');
|
|
53
|
+
const { withFreshIndex } = await import('../../memory/freshness.js');
|
|
54
|
+
const observations = await withFreshIndex(() => getProjectObservations(projectId));
|
|
55
|
+
const ids = observations.map((o) => o.id);
|
|
56
|
+
|
|
57
|
+
if (ids.length === 0) {
|
|
58
|
+
console.log('No observations found for this project.');
|
|
59
|
+
p.outro('No memories to purge.');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const result = await resolveObservations(ids, 'archived');
|
|
64
|
+
|
|
65
|
+
console.log(`[OK] Archived ${result.resolved.length} observations for project`);
|
|
66
|
+
|
|
67
|
+
p.outro(`Project memory purged. ${result.resolved.length} observations archived.`);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error(`[ERROR] Failed to purge project memory: ${err}`);
|
|
70
|
+
p.outro('Purge failed.');
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
function getProjectId(projectRoot: string): string {
|
|
76
|
+
try {
|
|
77
|
+
const { detectProject } = require('../project/detector.js');
|
|
78
|
+
const project = detectProject(projectRoot);
|
|
79
|
+
if (project) return project.id;
|
|
80
|
+
} catch { /* fallback below */ }
|
|
81
|
+
const normalized = projectRoot.replace(/\\/g, '/');
|
|
82
|
+
return `untracked/${normalized}`;
|
|
83
|
+
}
|
|
@@ -1,132 +1,132 @@
|
|
|
1
|
-
import { defineCommand } from 'citty';
|
|
2
|
-
import { compactSearch } from '../../compact/engine.js';
|
|
3
|
-
import { storeObservation } from '../../memory/observations.js';
|
|
4
|
-
import { emitError, emitResult, getCliProjectContext, parseCsvList, parsePositiveInt } from './operator-shared.js';
|
|
5
|
-
|
|
6
|
-
export default defineCommand({
|
|
7
|
-
meta: {
|
|
8
|
-
name: 'reasoning',
|
|
9
|
-
description: 'Store and search decision rationale from the operator CLI',
|
|
10
|
-
},
|
|
11
|
-
args: {
|
|
12
|
-
entity: { type: 'string', description: 'Entity this reasoning applies to' },
|
|
13
|
-
decision: { type: 'string', description: 'Decision that was made' },
|
|
14
|
-
rationale: { type: 'string', description: 'Why this approach was chosen' },
|
|
15
|
-
alternatives: { type: 'string', description: 'Comma-separated alternatives that were considered' },
|
|
16
|
-
constraints: { type: 'string', description: 'Comma-separated constraints' },
|
|
17
|
-
expectedOutcome: { type: 'string', description: 'Expected outcome from this decision' },
|
|
18
|
-
risks: { type: 'string', description: 'Comma-separated risks or downsides' },
|
|
19
|
-
concepts: { type: 'string', description: 'Comma-separated related concepts' },
|
|
20
|
-
files: { type: 'string', description: 'Comma-separated file list' },
|
|
21
|
-
relatedCommits: { type: 'string', description: 'Comma-separated related commit hashes' },
|
|
22
|
-
relatedEntities: { type: 'string', description: 'Comma-separated related entity names' },
|
|
23
|
-
query: { type: 'string', description: 'Search query for reasoning traces' },
|
|
24
|
-
limit: { type: 'string', description: 'Search result limit' },
|
|
25
|
-
scope: { type: 'string', description: 'project or global scope for search' },
|
|
26
|
-
json: { type: 'boolean', description: 'Emit machine-readable JSON output' },
|
|
27
|
-
},
|
|
28
|
-
run: async ({ args }) => {
|
|
29
|
-
const action = (args._ as string[])?.[0] || '';
|
|
30
|
-
const asJson = !!args.json;
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const { project } = await getCliProjectContext({ searchIndex: action === 'search' });
|
|
34
|
-
|
|
35
|
-
switch (action) {
|
|
36
|
-
case 'store': {
|
|
37
|
-
const entityName = (args.entity as string | undefined)?.trim();
|
|
38
|
-
const decision = (args.decision as string | undefined)?.trim();
|
|
39
|
-
const rationale = (args.rationale as string | undefined)?.trim();
|
|
40
|
-
if (!entityName || !decision || !rationale) {
|
|
41
|
-
emitError('entity, decision, and rationale are required for "memorix reasoning store"', asJson);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const alternatives = parseCsvList(args.alternatives as string | undefined);
|
|
46
|
-
const constraints = parseCsvList(args.constraints as string | undefined);
|
|
47
|
-
const risks = parseCsvList(args.risks as string | undefined);
|
|
48
|
-
const concepts = parseCsvList(args.concepts as string | undefined);
|
|
49
|
-
const filesModified = parseCsvList(args.files as string | undefined);
|
|
50
|
-
const relatedCommits = parseCsvList(args.relatedCommits as string | undefined);
|
|
51
|
-
const relatedEntities = parseCsvList(args.relatedEntities as string | undefined);
|
|
52
|
-
|
|
53
|
-
const narrativeParts: string[] = [rationale];
|
|
54
|
-
if (alternatives.length > 0) {
|
|
55
|
-
narrativeParts.push(`Alternatives considered: ${alternatives.join('; ')}`);
|
|
56
|
-
}
|
|
57
|
-
if (constraints.length > 0) {
|
|
58
|
-
narrativeParts.push(`Constraints: ${constraints.join('; ')}`);
|
|
59
|
-
}
|
|
60
|
-
if (args.expectedOutcome) {
|
|
61
|
-
narrativeParts.push(`Expected outcome: ${String(args.expectedOutcome).trim()}`);
|
|
62
|
-
}
|
|
63
|
-
if (risks.length > 0) {
|
|
64
|
-
narrativeParts.push(`Risks: ${risks.join('; ')}`);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const result = await storeObservation({
|
|
68
|
-
entityName,
|
|
69
|
-
type: 'reasoning',
|
|
70
|
-
title: decision,
|
|
71
|
-
narrative: narrativeParts.join('. '),
|
|
72
|
-
facts: [
|
|
73
|
-
`Decision: ${decision}`,
|
|
74
|
-
...alternatives.map((item) => `Alternative: ${item}`),
|
|
75
|
-
...constraints.map((item) => `Constraint: ${item}`),
|
|
76
|
-
...(args.expectedOutcome ? [`Expected outcome: ${String(args.expectedOutcome).trim()}`] : []),
|
|
77
|
-
...risks.map((item) => `Risk: ${item}`),
|
|
78
|
-
...relatedCommits.map((item) => `Commit: ${item}`),
|
|
79
|
-
...relatedEntities.map((item) => `Related entity: ${item}`),
|
|
80
|
-
],
|
|
81
|
-
concepts,
|
|
82
|
-
filesModified,
|
|
83
|
-
relatedCommits,
|
|
84
|
-
relatedEntities,
|
|
85
|
-
projectId: project.id,
|
|
86
|
-
source: 'manual',
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
emitResult(
|
|
90
|
-
{ project, observation: result.observation, upserted: result.upserted },
|
|
91
|
-
`${result.upserted ? 'Updated' : 'Stored'} reasoning trace #${result.observation.id}: ${decision}`,
|
|
92
|
-
asJson,
|
|
93
|
-
);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
case 'search': {
|
|
98
|
-
const query = (args.query as string | undefined)?.trim();
|
|
99
|
-
if (!query) {
|
|
100
|
-
emitError('query is required for "memorix reasoning search"', asJson);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const scope = (args.scope as string | undefined) === 'global' ? 'global' : 'project';
|
|
104
|
-
const limit = parsePositiveInt(args.limit as string | undefined, 10);
|
|
105
|
-
const result = await compactSearch({
|
|
106
|
-
query,
|
|
107
|
-
limit,
|
|
108
|
-
type: 'reasoning',
|
|
109
|
-
projectId: scope === 'global' ? undefined : project.id,
|
|
110
|
-
status: 'active',
|
|
111
|
-
});
|
|
112
|
-
emitResult(
|
|
113
|
-
{ project, scope, entries: result.entries },
|
|
114
|
-
result.entries.length === 0 ? 'No reasoning traces found.' : `[REASONING] Reasoning traces\n${result.formatted}`,
|
|
115
|
-
asJson,
|
|
116
|
-
);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
default:
|
|
121
|
-
console.log('Memorix Reasoning Commands');
|
|
122
|
-
console.log('');
|
|
123
|
-
console.log('Usage:');
|
|
124
|
-
console.log(' memorix reasoning store --entity auth --decision "Use SQLite" --rationale "..."');
|
|
125
|
-
console.log(' memorix reasoning search --query "why sqlite" [--scope project|global --limit 10]');
|
|
126
|
-
}
|
|
127
|
-
} catch (error) {
|
|
128
|
-
emitError(error instanceof Error ? error.message : String(error), asJson);
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
|
|
1
|
+
import { defineCommand } from 'citty';
|
|
2
|
+
import { compactSearch } from '../../compact/engine.js';
|
|
3
|
+
import { storeObservation } from '../../memory/observations.js';
|
|
4
|
+
import { emitError, emitResult, getCliProjectContext, parseCsvList, parsePositiveInt } from './operator-shared.js';
|
|
5
|
+
|
|
6
|
+
export default defineCommand({
|
|
7
|
+
meta: {
|
|
8
|
+
name: 'reasoning',
|
|
9
|
+
description: 'Store and search decision rationale from the operator CLI',
|
|
10
|
+
},
|
|
11
|
+
args: {
|
|
12
|
+
entity: { type: 'string', description: 'Entity this reasoning applies to' },
|
|
13
|
+
decision: { type: 'string', description: 'Decision that was made' },
|
|
14
|
+
rationale: { type: 'string', description: 'Why this approach was chosen' },
|
|
15
|
+
alternatives: { type: 'string', description: 'Comma-separated alternatives that were considered' },
|
|
16
|
+
constraints: { type: 'string', description: 'Comma-separated constraints' },
|
|
17
|
+
expectedOutcome: { type: 'string', description: 'Expected outcome from this decision' },
|
|
18
|
+
risks: { type: 'string', description: 'Comma-separated risks or downsides' },
|
|
19
|
+
concepts: { type: 'string', description: 'Comma-separated related concepts' },
|
|
20
|
+
files: { type: 'string', description: 'Comma-separated file list' },
|
|
21
|
+
relatedCommits: { type: 'string', description: 'Comma-separated related commit hashes' },
|
|
22
|
+
relatedEntities: { type: 'string', description: 'Comma-separated related entity names' },
|
|
23
|
+
query: { type: 'string', description: 'Search query for reasoning traces' },
|
|
24
|
+
limit: { type: 'string', description: 'Search result limit' },
|
|
25
|
+
scope: { type: 'string', description: 'project or global scope for search' },
|
|
26
|
+
json: { type: 'boolean', description: 'Emit machine-readable JSON output' },
|
|
27
|
+
},
|
|
28
|
+
run: async ({ args }) => {
|
|
29
|
+
const action = (args._ as string[])?.[0] || '';
|
|
30
|
+
const asJson = !!args.json;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const { project } = await getCliProjectContext({ searchIndex: action === 'search' });
|
|
34
|
+
|
|
35
|
+
switch (action) {
|
|
36
|
+
case 'store': {
|
|
37
|
+
const entityName = (args.entity as string | undefined)?.trim();
|
|
38
|
+
const decision = (args.decision as string | undefined)?.trim();
|
|
39
|
+
const rationale = (args.rationale as string | undefined)?.trim();
|
|
40
|
+
if (!entityName || !decision || !rationale) {
|
|
41
|
+
emitError('entity, decision, and rationale are required for "memorix reasoning store"', asJson);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const alternatives = parseCsvList(args.alternatives as string | undefined);
|
|
46
|
+
const constraints = parseCsvList(args.constraints as string | undefined);
|
|
47
|
+
const risks = parseCsvList(args.risks as string | undefined);
|
|
48
|
+
const concepts = parseCsvList(args.concepts as string | undefined);
|
|
49
|
+
const filesModified = parseCsvList(args.files as string | undefined);
|
|
50
|
+
const relatedCommits = parseCsvList(args.relatedCommits as string | undefined);
|
|
51
|
+
const relatedEntities = parseCsvList(args.relatedEntities as string | undefined);
|
|
52
|
+
|
|
53
|
+
const narrativeParts: string[] = [rationale];
|
|
54
|
+
if (alternatives.length > 0) {
|
|
55
|
+
narrativeParts.push(`Alternatives considered: ${alternatives.join('; ')}`);
|
|
56
|
+
}
|
|
57
|
+
if (constraints.length > 0) {
|
|
58
|
+
narrativeParts.push(`Constraints: ${constraints.join('; ')}`);
|
|
59
|
+
}
|
|
60
|
+
if (args.expectedOutcome) {
|
|
61
|
+
narrativeParts.push(`Expected outcome: ${String(args.expectedOutcome).trim()}`);
|
|
62
|
+
}
|
|
63
|
+
if (risks.length > 0) {
|
|
64
|
+
narrativeParts.push(`Risks: ${risks.join('; ')}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const result = await storeObservation({
|
|
68
|
+
entityName,
|
|
69
|
+
type: 'reasoning',
|
|
70
|
+
title: decision,
|
|
71
|
+
narrative: narrativeParts.join('. '),
|
|
72
|
+
facts: [
|
|
73
|
+
`Decision: ${decision}`,
|
|
74
|
+
...alternatives.map((item) => `Alternative: ${item}`),
|
|
75
|
+
...constraints.map((item) => `Constraint: ${item}`),
|
|
76
|
+
...(args.expectedOutcome ? [`Expected outcome: ${String(args.expectedOutcome).trim()}`] : []),
|
|
77
|
+
...risks.map((item) => `Risk: ${item}`),
|
|
78
|
+
...relatedCommits.map((item) => `Commit: ${item}`),
|
|
79
|
+
...relatedEntities.map((item) => `Related entity: ${item}`),
|
|
80
|
+
],
|
|
81
|
+
concepts,
|
|
82
|
+
filesModified,
|
|
83
|
+
relatedCommits,
|
|
84
|
+
relatedEntities,
|
|
85
|
+
projectId: project.id,
|
|
86
|
+
source: 'manual',
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
emitResult(
|
|
90
|
+
{ project, observation: result.observation, upserted: result.upserted },
|
|
91
|
+
`${result.upserted ? 'Updated' : 'Stored'} reasoning trace #${result.observation.id}: ${decision}`,
|
|
92
|
+
asJson,
|
|
93
|
+
);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
case 'search': {
|
|
98
|
+
const query = (args.query as string | undefined)?.trim();
|
|
99
|
+
if (!query) {
|
|
100
|
+
emitError('query is required for "memorix reasoning search"', asJson);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const scope = (args.scope as string | undefined) === 'global' ? 'global' : 'project';
|
|
104
|
+
const limit = parsePositiveInt(args.limit as string | undefined, 10);
|
|
105
|
+
const result = await compactSearch({
|
|
106
|
+
query,
|
|
107
|
+
limit,
|
|
108
|
+
type: 'reasoning',
|
|
109
|
+
projectId: scope === 'global' ? undefined : project.id,
|
|
110
|
+
status: 'active',
|
|
111
|
+
});
|
|
112
|
+
emitResult(
|
|
113
|
+
{ project, scope, entries: result.entries },
|
|
114
|
+
result.entries.length === 0 ? 'No reasoning traces found.' : `[REASONING] Reasoning traces\n${result.formatted}`,
|
|
115
|
+
asJson,
|
|
116
|
+
);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
default:
|
|
121
|
+
console.log('Memorix Reasoning Commands');
|
|
122
|
+
console.log('');
|
|
123
|
+
console.log('Usage:');
|
|
124
|
+
console.log(' memorix reasoning store --entity auth --decision "Use SQLite" --rationale "..."');
|
|
125
|
+
console.log(' memorix reasoning search --query "why sqlite" [--scope project|global --limit 10]');
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
emitError(error instanceof Error ? error.message : String(error), asJson);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memorix repair — Safe repair entry points for Memorix-owned integration files.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { defineCommand } from 'citty';
|
|
6
|
+
|
|
7
|
+
export default defineCommand({
|
|
8
|
+
meta: {
|
|
9
|
+
name: 'repair',
|
|
10
|
+
description: 'Repair Memorix-owned agent integration files',
|
|
11
|
+
},
|
|
12
|
+
args: {
|
|
13
|
+
agent: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'Agent to repair (default: all detected repairable entries)',
|
|
16
|
+
},
|
|
17
|
+
scope: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
description: 'Scope: local, project, global, or all',
|
|
20
|
+
},
|
|
21
|
+
dry: {
|
|
22
|
+
type: 'boolean',
|
|
23
|
+
description: 'Show what would be repaired without writing files',
|
|
24
|
+
default: false,
|
|
25
|
+
},
|
|
26
|
+
json: {
|
|
27
|
+
type: 'boolean',
|
|
28
|
+
description: 'Emit machine-readable JSON output',
|
|
29
|
+
default: false,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
run: async ({ args }) => {
|
|
33
|
+
const positional = (args._ as string[]) ?? [];
|
|
34
|
+
const action = positional[0] || 'agents';
|
|
35
|
+
|
|
36
|
+
if (action !== 'agents') {
|
|
37
|
+
const message = 'Usage: memorix repair agents [--agent <agent>] [--scope local|project|global|all] [--dry]';
|
|
38
|
+
if (args.json) {
|
|
39
|
+
console.log(JSON.stringify({ error: message }, null, 2));
|
|
40
|
+
} else {
|
|
41
|
+
console.log(message);
|
|
42
|
+
}
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const { repairAgentIntegrations, formatAgentRepairResult } = await import('./agent-integrations.js');
|
|
48
|
+
const repair = await repairAgentIntegrations({
|
|
49
|
+
agent: args.agent as string | undefined,
|
|
50
|
+
scope: args.scope as string | undefined,
|
|
51
|
+
dry: !!args.dry,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (args.json) {
|
|
55
|
+
console.log(JSON.stringify({ repair }, null, 2));
|
|
56
|
+
} else {
|
|
57
|
+
console.log(formatAgentRepairResult(repair));
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|