mindlore 0.7.2 → 0.7.4
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/.claude-plugin/marketplace.json +33 -0
- package/.claude-plugin/plugin.json +30 -0
- package/dist/scripts/init.js +152 -151
- package/dist/scripts/init.js.map +1 -1
- package/dist/scripts/lib/constants.d.ts +1 -1
- package/dist/scripts/lib/constants.d.ts.map +1 -1
- package/dist/scripts/lib/constants.js +2 -7
- package/dist/scripts/lib/constants.js.map +1 -1
- package/dist/scripts/lib/detect-plugin.d.ts +2 -0
- package/dist/scripts/lib/detect-plugin.d.ts.map +1 -0
- package/dist/scripts/lib/detect-plugin.js +14 -0
- package/dist/scripts/lib/detect-plugin.js.map +1 -0
- package/dist/scripts/lib/hook-helpers.d.ts +8 -0
- package/dist/scripts/lib/hook-helpers.d.ts.map +1 -0
- package/dist/scripts/lib/hook-helpers.js +27 -0
- package/dist/scripts/lib/hook-helpers.js.map +1 -0
- package/dist/scripts/lib/mcp-namespace.d.ts.map +1 -1
- package/dist/scripts/lib/mcp-namespace.js +0 -5
- package/dist/scripts/lib/mcp-namespace.js.map +1 -1
- package/dist/scripts/lib/mcp-tools.d.ts.map +1 -1
- package/dist/scripts/lib/mcp-tools.js +3 -19
- package/dist/scripts/lib/mcp-tools.js.map +1 -1
- package/dist/scripts/lib/relation-helpers.js +1 -1
- package/dist/scripts/lib/relation-helpers.js.map +1 -1
- package/dist/scripts/lib/session-payload.d.ts.map +1 -1
- package/dist/scripts/lib/session-payload.js +4 -16
- package/dist/scripts/lib/session-payload.js.map +1 -1
- package/dist/scripts/lib/settings-cleanup.d.ts +6 -0
- package/dist/scripts/lib/settings-cleanup.d.ts.map +1 -0
- package/dist/scripts/lib/settings-cleanup.js +61 -0
- package/dist/scripts/lib/settings-cleanup.js.map +1 -0
- package/dist/scripts/lib/tool-adapters/decide-adapter.d.ts +1 -1
- package/dist/scripts/lib/tool-adapters/decide-adapter.d.ts.map +1 -1
- package/dist/scripts/lib/tool-adapters/decide-adapter.js +5 -0
- package/dist/scripts/lib/tool-adapters/decide-adapter.js.map +1 -1
- package/dist/scripts/mcp-server.js +40 -3
- package/dist/scripts/mcp-server.js.map +1 -1
- package/dist/scripts/mindlore-doctor.d.ts +4 -1
- package/dist/scripts/mindlore-doctor.d.ts.map +1 -1
- package/dist/scripts/mindlore-doctor.js +86 -40
- package/dist/scripts/mindlore-doctor.js.map +1 -1
- package/dist/scripts/mindlore-health-check.js +2 -2
- package/dist/scripts/mindlore-health-check.js.map +1 -1
- package/dist/scripts/mindlore-perf.d.ts +3 -1
- package/dist/scripts/mindlore-perf.d.ts.map +1 -1
- package/dist/scripts/mindlore-perf.js +13 -6
- package/dist/scripts/mindlore-perf.js.map +1 -1
- package/dist/scripts/uninstall.js +14 -38
- package/dist/scripts/uninstall.js.map +1 -1
- package/dist/tests/db-singleton.test.d.ts +2 -0
- package/dist/tests/db-singleton.test.d.ts.map +1 -0
- package/dist/tests/db-singleton.test.js +22 -0
- package/dist/tests/db-singleton.test.js.map +1 -0
- package/dist/tests/doctor.test.js +45 -15
- package/dist/tests/doctor.test.js.map +1 -1
- package/dist/tests/dont-repeat-dedup.test.js +13 -1
- package/dist/tests/dont-repeat-dedup.test.js.map +1 -1
- package/dist/tests/fts5-sync.test.js +11 -117
- package/dist/tests/fts5-sync.test.js.map +1 -1
- package/dist/tests/hook-helpers.test.d.ts +2 -0
- package/dist/tests/hook-helpers.test.d.ts.map +1 -0
- package/dist/tests/hook-helpers.test.js +44 -0
- package/dist/tests/hook-helpers.test.js.map +1 -0
- package/dist/tests/install-matrix.test.d.ts +2 -0
- package/dist/tests/install-matrix.test.d.ts.map +1 -0
- package/dist/tests/install-matrix.test.js +110 -0
- package/dist/tests/install-matrix.test.js.map +1 -0
- package/dist/tests/latency-budget.test.d.ts +2 -0
- package/dist/tests/latency-budget.test.d.ts.map +1 -0
- package/dist/tests/latency-budget.test.js +37 -0
- package/dist/tests/latency-budget.test.js.map +1 -0
- package/dist/tests/mcp-namespace.test.d.ts +2 -0
- package/dist/tests/mcp-namespace.test.d.ts.map +1 -0
- package/dist/tests/mcp-namespace.test.js +41 -0
- package/dist/tests/mcp-namespace.test.js.map +1 -0
- package/dist/tests/session-payload.test.js +13 -5
- package/dist/tests/session-payload.test.js.map +1 -1
- package/dist/tests/settings-cleanup.test.d.ts +2 -0
- package/dist/tests/settings-cleanup.test.d.ts.map +1 -0
- package/dist/tests/settings-cleanup.test.js +126 -0
- package/dist/tests/settings-cleanup.test.js.map +1 -0
- package/dist/tests/telemetry-perf.test.js +9 -8
- package/dist/tests/telemetry-perf.test.js.map +1 -1
- package/dist/tests/version-sync.test.d.ts +2 -0
- package/dist/tests/version-sync.test.d.ts.map +1 -0
- package/dist/tests/version-sync.test.js +41 -0
- package/dist/tests/version-sync.test.js.map +1 -0
- package/hooks/cc-memory-bulk-sync.cjs +2 -5
- package/hooks/cc-session-sync.cjs +2 -5
- package/hooks/lib/mindlore-common.cjs +41 -8
- package/hooks/mindlore-fts5-sync.cjs +5 -1
- package/hooks/mindlore-search.cjs +20 -14
- package/hooks/mindlore-session-focus.cjs +5 -17
- package/hooks/src/mindlore-fts5-sync.cjs +7 -4
- package/hooks/src/mindlore-search.cjs +19 -11
- package/hooks/src/mindlore-session-focus.cjs +1 -1
- package/package.json +3 -2
- package/plugin.json +5 -2
- package/skills/mindlore-decide/SKILL.md +7 -0
- package/skills/mindlore-log/SKILL.md +7 -0
- package/templates/config.json +1 -1
|
@@ -8,22 +8,13 @@ const path_1 = __importDefault(require("path"));
|
|
|
8
8
|
const os_1 = __importDefault(require("os"));
|
|
9
9
|
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
10
10
|
describe('mindlore-doctor', () => {
|
|
11
|
-
it('detects
|
|
11
|
+
it('detects hooks from plugin.json (auto-discovery)', () => {
|
|
12
12
|
const { checkHooks } = require('../dist/scripts/mindlore-doctor.js');
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
expect(result.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const { checkHooks } = require('../dist/scripts/mindlore-doctor.js');
|
|
19
|
-
const settings = {
|
|
20
|
-
hooks: {
|
|
21
|
-
SessionStart: [{ command: 'mindlore-session-focus' }],
|
|
22
|
-
UserPromptSubmit: [{ command: 'mindlore-search' }],
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
const result = checkHooks(settings);
|
|
26
|
-
expect(result.found).toBeGreaterThan(0);
|
|
13
|
+
// checkHooks now reads plugin.json, not settings.json
|
|
14
|
+
const result = checkHooks();
|
|
15
|
+
expect(result.pass).toBe(true);
|
|
16
|
+
expect(result.found).toBeGreaterThanOrEqual(14);
|
|
17
|
+
expect(result.message).toContain('plugin.json');
|
|
27
18
|
});
|
|
28
19
|
it('detects correct Node version', () => {
|
|
29
20
|
const { checkNodeVersion } = require('../dist/scripts/mindlore-doctor.js');
|
|
@@ -78,5 +69,44 @@ describe('mindlore-doctor', () => {
|
|
|
78
69
|
expect(derived).toContain(name);
|
|
79
70
|
}
|
|
80
71
|
});
|
|
72
|
+
describe('stale local DB detection', () => {
|
|
73
|
+
it('warns when cwd has .mindlore/mindlore.db without schema_version', () => {
|
|
74
|
+
const tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'mindlore-doctor-'));
|
|
75
|
+
const localMindlore = path_1.default.join(tmpDir, '.mindlore');
|
|
76
|
+
fs_1.default.mkdirSync(localMindlore, { recursive: true });
|
|
77
|
+
// Create a minimal SQLite DB without mindlore_schema_version
|
|
78
|
+
const Database = require('better-sqlite3');
|
|
79
|
+
const db = new Database(path_1.default.join(localMindlore, 'mindlore.db'));
|
|
80
|
+
db.exec("CREATE VIRTUAL TABLE mindlore_fts USING fts5(path, slug, content, tokenize='porter')");
|
|
81
|
+
db.close();
|
|
82
|
+
const { checkStaleLocalDb } = require('../dist/scripts/mindlore-doctor.js');
|
|
83
|
+
const result = checkStaleLocalDb(tmpDir);
|
|
84
|
+
expect(result.pass).toBe(false);
|
|
85
|
+
expect(result.message).toContain('Stale local');
|
|
86
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
87
|
+
});
|
|
88
|
+
it('passes when no local .mindlore exists', () => {
|
|
89
|
+
const tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'mindlore-doctor-'));
|
|
90
|
+
const { checkStaleLocalDb } = require('../dist/scripts/mindlore-doctor.js');
|
|
91
|
+
const result = checkStaleLocalDb(tmpDir);
|
|
92
|
+
expect(result.pass).toBe(true);
|
|
93
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe('plugin cache regression', () => {
|
|
97
|
+
it('hook resolves bundled scripts from plugin cache __dirname', () => {
|
|
98
|
+
// Simulate plugin cache directory structure
|
|
99
|
+
const tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'mindlore-cache-'));
|
|
100
|
+
const hookDir = path_1.default.join(tmpDir, 'hooks');
|
|
101
|
+
const libDir = path_1.default.join(tmpDir, 'hooks', 'lib');
|
|
102
|
+
fs_1.default.mkdirSync(libDir, { recursive: true });
|
|
103
|
+
// Create a minimal hook that resolves a bundled script
|
|
104
|
+
fs_1.default.writeFileSync(path_1.default.join(libDir, 'mindlore-common.cjs'), 'module.exports = {};');
|
|
105
|
+
// Verify resolution works from plugin cache path
|
|
106
|
+
const resolved = path_1.default.resolve(hookDir, 'lib', 'mindlore-common.cjs');
|
|
107
|
+
expect(fs_1.default.existsSync(resolved)).toBe(true);
|
|
108
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
109
|
+
});
|
|
110
|
+
});
|
|
81
111
|
});
|
|
82
112
|
//# sourceMappingURL=doctor.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.test.js","sourceRoot":"","sources":["../../tests/doctor.test.ts"],"names":[],"mappings":";;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AACpB,oEAAsC;AAEtC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"doctor.test.js","sourceRoot":"","sources":["../../tests/doctor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,8 @@ const os_1 = __importDefault(require("os"));
|
|
|
9
9
|
const child_process_1 = require("child_process");
|
|
10
10
|
const HOOK_PATH = path_1.default.join(__dirname, '..', 'hooks', 'mindlore-dont-repeat.cjs');
|
|
11
11
|
function runHook(input, settingsContent) {
|
|
12
|
-
const
|
|
12
|
+
const homeDir = process.env.USERPROFILE || os_1.default.homedir();
|
|
13
|
+
const realSettings = path_1.default.join(homeDir, '.claude', 'settings.json');
|
|
13
14
|
let backup = null;
|
|
14
15
|
const claudeDir = path_1.default.dirname(realSettings);
|
|
15
16
|
if (settingsContent !== undefined) {
|
|
@@ -57,6 +58,17 @@ describe('dont-repeat dedup with lessons-enforcement', () => {
|
|
|
57
58
|
new_string: 'appendFileSync is dangerous pattern that should trigger',
|
|
58
59
|
},
|
|
59
60
|
};
|
|
61
|
+
let origUserProfile;
|
|
62
|
+
let tmpHome;
|
|
63
|
+
beforeAll(() => {
|
|
64
|
+
origUserProfile = process.env.USERPROFILE;
|
|
65
|
+
tmpHome = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'mindlore-test-home-'));
|
|
66
|
+
process.env.USERPROFILE = tmpHome;
|
|
67
|
+
});
|
|
68
|
+
afterAll(() => {
|
|
69
|
+
process.env.USERPROFILE = origUserProfile;
|
|
70
|
+
fs_1.default.rmSync(tmpHome, { recursive: true, force: true });
|
|
71
|
+
});
|
|
60
72
|
it('exits silently when lessons-enforcement hook is registered', () => {
|
|
61
73
|
const settings = JSON.stringify({
|
|
62
74
|
hooks: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dont-repeat-dedup.test.js","sourceRoot":"","sources":["../../tests/dont-repeat-dedup.test.ts"],"names":[],"mappings":";;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AACpB,iDAA6C;AAE7C,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,0BAA0B,CAAC,CAAC;AAElF,SAAS,OAAO,CAAC,KAAa,EAAE,eAAwB;IACtD,MAAM,
|
|
1
|
+
{"version":3,"file":"dont-repeat-dedup.test.js","sourceRoot":"","sources":["../../tests/dont-repeat-dedup.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,124 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
const DB_PATH = path_1.default.join(TEST_DIR, 'mindlore.db');
|
|
11
|
-
const SOURCES_DIR = path_1.default.join(TEST_DIR, 'sources');
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
(0, db_js_1.setupTestDir)(TEST_DIR, ['sources', 'raw']);
|
|
14
|
-
const db = (0, db_js_1.createTestDb)(DB_PATH);
|
|
15
|
-
db.close();
|
|
16
|
-
});
|
|
17
|
-
afterEach(() => {
|
|
18
|
-
(0, db_js_1.teardownTestDir)(TEST_DIR);
|
|
19
|
-
});
|
|
20
|
-
describe('FTS5 Incremental Sync', () => {
|
|
21
|
-
test('should index a new file incrementally', () => {
|
|
22
|
-
const Database = require('better-sqlite3');
|
|
23
|
-
const { sha256, parseFrontmatter, extractFtsMetadata, insertFtsRow } = require('../hooks/lib/mindlore-common.cjs');
|
|
24
|
-
const db = new Database(DB_PATH);
|
|
25
|
-
const filePath = path_1.default.join(SOURCES_DIR, 'new-doc.md');
|
|
26
|
-
const content = '---\nslug: new-doc\ntype: source\ntitle: New Doc\ntags: [test]\nquality: medium\ndate_captured: 2026-04-12\n---\n\n# New Doc\n\nIncremental sync test content.';
|
|
27
|
-
fs_1.default.writeFileSync(filePath, content);
|
|
28
|
-
// Simulate what fts5-sync hook does: parse frontmatter + extract metadata + insert
|
|
29
|
-
const raw = fs_1.default.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
|
|
30
|
-
const hash = sha256(raw);
|
|
31
|
-
const { meta: fm, body } = parseFrontmatter(raw);
|
|
32
|
-
const meta = extractFtsMetadata(fm, body, filePath, TEST_DIR);
|
|
33
|
-
insertFtsRow(db, {
|
|
34
|
-
path: filePath,
|
|
35
|
-
slug: meta.slug,
|
|
36
|
-
description: meta.description,
|
|
37
|
-
type: meta.type,
|
|
38
|
-
category: meta.category,
|
|
39
|
-
title: meta.title,
|
|
40
|
-
content: meta.content,
|
|
41
|
-
tags: meta.tags,
|
|
42
|
-
quality: meta.quality,
|
|
43
|
-
dateCaptured: meta.dateCaptured,
|
|
44
|
-
});
|
|
45
|
-
// Update file hash
|
|
46
|
-
db.prepare(`INSERT OR REPLACE INTO file_hashes (path, content_hash, last_indexed) VALUES (?, ?, datetime('now'))`).run(filePath, hash);
|
|
47
|
-
// Verify indexed
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
|
|
49
|
-
const result = db.prepare('SELECT count(*) as cnt FROM mindlore_fts WHERE path = ?').get(filePath);
|
|
50
|
-
expect(result.cnt).toBe(1);
|
|
51
|
-
// Verify hash stored
|
|
52
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
|
|
53
|
-
const hashRow = db.prepare('SELECT content_hash FROM file_hashes WHERE path = ?').get(filePath);
|
|
54
|
-
expect(hashRow.content_hash).toBe(hash);
|
|
55
|
-
db.close();
|
|
3
|
+
describe('fts5-sync guard', () => {
|
|
4
|
+
it('skips non-.md trigger files', () => {
|
|
5
|
+
const { shouldIndexFile } = require('../hooks/mindlore-fts5-sync.cjs');
|
|
6
|
+
expect(shouldIndexFile('/path/to/file.ts')).toBe(false);
|
|
56
7
|
});
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
const db = new Database(DB_PATH);
|
|
61
|
-
const filePath = path_1.default.join(SOURCES_DIR, 'unchanged.md');
|
|
62
|
-
const content = '---\nslug: unchanged\ntype: source\ntitle: Unchanged\ntags: []\nquality: low\n---\n\n# Unchanged\n\nThis will not change.';
|
|
63
|
-
fs_1.default.writeFileSync(filePath, content);
|
|
64
|
-
const raw = fs_1.default.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
|
|
65
|
-
const hash = sha256(raw);
|
|
66
|
-
const { meta: fm, body } = parseFrontmatter(raw);
|
|
67
|
-
const meta = extractFtsMetadata(fm, body, filePath, TEST_DIR);
|
|
68
|
-
// First insert
|
|
69
|
-
insertFtsRow(db, {
|
|
70
|
-
path: filePath,
|
|
71
|
-
slug: meta.slug,
|
|
72
|
-
description: meta.description,
|
|
73
|
-
type: meta.type,
|
|
74
|
-
category: meta.category,
|
|
75
|
-
title: meta.title,
|
|
76
|
-
content: meta.content,
|
|
77
|
-
tags: meta.tags,
|
|
78
|
-
quality: meta.quality,
|
|
79
|
-
dateCaptured: meta.dateCaptured,
|
|
80
|
-
});
|
|
81
|
-
db.prepare(`INSERT OR REPLACE INTO file_hashes (path, content_hash, last_indexed) VALUES (?, ?, datetime('now'))`).run(filePath, hash);
|
|
82
|
-
// Re-read same file — hash should match, skip re-index
|
|
83
|
-
const raw2 = fs_1.default.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
|
|
84
|
-
const hash2 = sha256(raw2);
|
|
85
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
|
|
86
|
-
const existingHash = db.prepare('SELECT content_hash FROM file_hashes WHERE path = ?').get(filePath);
|
|
87
|
-
expect(existingHash).toBeDefined();
|
|
88
|
-
expect(hash2).toBe(existingHash.content_hash);
|
|
89
|
-
db.close();
|
|
8
|
+
it('processes .md trigger files', () => {
|
|
9
|
+
const { shouldIndexFile } = require('../hooks/mindlore-fts5-sync.cjs');
|
|
10
|
+
expect(shouldIndexFile('/path/to/file.md')).toBe(true);
|
|
90
11
|
});
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const filePath = path_1.default.join(SOURCES_DIR, 'changing.md');
|
|
96
|
-
const content1 = '---\nslug: changing\ntype: source\ntitle: Version 1\ntags: [v1]\nquality: low\n---\n\n# Version 1\n\nOriginal content.';
|
|
97
|
-
fs_1.default.writeFileSync(filePath, content1);
|
|
98
|
-
const raw1 = content1.replace(/\r\n/g, '\n');
|
|
99
|
-
const hash1 = sha256(raw1);
|
|
100
|
-
const { meta: fm1, body: body1 } = parseFrontmatter(raw1);
|
|
101
|
-
const meta1 = extractFtsMetadata(fm1, body1, filePath, TEST_DIR);
|
|
102
|
-
insertFtsRow(db, { path: filePath, slug: meta1.slug, description: meta1.description, type: meta1.type, category: meta1.category, title: meta1.title, content: meta1.content, tags: meta1.tags, quality: meta1.quality, dateCaptured: meta1.dateCaptured });
|
|
103
|
-
db.prepare(`INSERT OR REPLACE INTO file_hashes (path, content_hash, last_indexed) VALUES (?, ?, datetime('now'))`).run(filePath, hash1);
|
|
104
|
-
// Change file
|
|
105
|
-
const content2 = '---\nslug: changing\ntype: source\ntitle: Version 2\ntags: [v2]\nquality: high\n---\n\n# Version 2\n\nUpdated content with new info.';
|
|
106
|
-
fs_1.default.writeFileSync(filePath, content2);
|
|
107
|
-
const raw2 = content2.replace(/\r\n/g, '\n');
|
|
108
|
-
const hash2 = sha256(raw2);
|
|
109
|
-
// Hash should differ
|
|
110
|
-
expect(hash2).not.toBe(hash1);
|
|
111
|
-
// Re-index: delete old + insert new
|
|
112
|
-
db.prepare('DELETE FROM mindlore_fts WHERE path = ?').run(filePath);
|
|
113
|
-
const { meta: fm2, body: body2 } = parseFrontmatter(raw2);
|
|
114
|
-
const meta2 = extractFtsMetadata(fm2, body2, filePath, TEST_DIR);
|
|
115
|
-
insertFtsRow(db, { path: filePath, slug: meta2.slug, description: meta2.description, type: meta2.type, category: meta2.category, title: meta2.title, content: meta2.content, tags: meta2.tags, quality: meta2.quality, dateCaptured: meta2.dateCaptured });
|
|
116
|
-
db.prepare(`INSERT OR REPLACE INTO file_hashes (path, content_hash, last_indexed) VALUES (?, ?, datetime('now'))`).run(filePath, hash2);
|
|
117
|
-
// Verify updated
|
|
118
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
|
|
119
|
-
const row = db.prepare('SELECT title FROM mindlore_fts WHERE path = ?').get(filePath);
|
|
120
|
-
expect(row.title).toBe('Version 2');
|
|
121
|
-
db.close();
|
|
12
|
+
it('handles empty/undefined path', () => {
|
|
13
|
+
const { shouldIndexFile } = require('../hooks/mindlore-fts5-sync.cjs');
|
|
14
|
+
expect(shouldIndexFile('')).toBe(false);
|
|
15
|
+
expect(shouldIndexFile(undefined)).toBe(false);
|
|
122
16
|
});
|
|
123
17
|
});
|
|
124
18
|
//# sourceMappingURL=fts5-sync.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fts5-sync.test.js","sourceRoot":"","sources":["../../tests/fts5-sync.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fts5-sync.test.js","sourceRoot":"","sources":["../../tests/fts5-sync.test.ts"],"names":[],"mappings":";;AAAA,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,iCAAiC,CAAC,CAAC;QACvE,MAAM,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,iCAAiC,CAAC,CAAC;QACvE,MAAM,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,iCAAiC,CAAC,CAAC;QACvE,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-helpers.test.d.ts","sourceRoot":"","sources":["../../tests/hook-helpers.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const hook_helpers_js_1 = require("../scripts/lib/hook-helpers.js");
|
|
4
|
+
describe('hook-helpers', () => {
|
|
5
|
+
describe('unwrapHookEntries', () => {
|
|
6
|
+
it('returns array from nested hooks', () => {
|
|
7
|
+
const entry = { hooks: [{ command: 'a' }, { command: 'b' }] };
|
|
8
|
+
expect((0, hook_helpers_js_1.unwrapHookEntries)(entry)).toEqual([{ command: 'a' }, { command: 'b' }]);
|
|
9
|
+
});
|
|
10
|
+
it('wraps single entry in array', () => {
|
|
11
|
+
const entry = { command: 'solo' };
|
|
12
|
+
expect((0, hook_helpers_js_1.unwrapHookEntries)(entry)).toEqual([{ command: 'solo' }]);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe('isMindloreHook', () => {
|
|
16
|
+
it('detects mindlore hook in nested', () => {
|
|
17
|
+
expect((0, hook_helpers_js_1.isMindloreHook)({ hooks: [{ command: 'node mindlore-search.cjs' }] })).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
it('returns false for non-mindlore', () => {
|
|
20
|
+
expect((0, hook_helpers_js_1.isMindloreHook)({ command: 'node other-hook.cjs' })).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe('countMindloreHooks', () => {
|
|
24
|
+
it('counts across events', () => {
|
|
25
|
+
const hooks = {
|
|
26
|
+
UserPromptSubmit: [
|
|
27
|
+
{ hooks: [{ command: 'node mindlore-search.cjs' }, { command: 'node mindlore-decision.cjs' }] },
|
|
28
|
+
],
|
|
29
|
+
SessionStart: [{ command: 'node mindlore-session-focus.cjs' }],
|
|
30
|
+
};
|
|
31
|
+
expect((0, hook_helpers_js_1.countMindloreHooks)(hooks)).toBe(3);
|
|
32
|
+
});
|
|
33
|
+
it('returns 0 for empty', () => {
|
|
34
|
+
expect((0, hook_helpers_js_1.countMindloreHooks)({})).toBe(0);
|
|
35
|
+
});
|
|
36
|
+
it('skips non-object entries gracefully', () => {
|
|
37
|
+
const hooks = {
|
|
38
|
+
SessionStart: [null, undefined, 42, 'string', { command: 'node mindlore-search.cjs' }],
|
|
39
|
+
};
|
|
40
|
+
expect((0, hook_helpers_js_1.countMindloreHooks)(hooks)).toBe(1);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=hook-helpers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-helpers.test.js","sourceRoot":"","sources":["../../tests/hook-helpers.test.ts"],"names":[],"mappings":";;AAAA,oEAAuG;AAEvG,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;YAC9D,MAAM,CAAC,IAAA,mCAAiB,EAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YAClC,MAAM,CAAC,IAAA,mCAAiB,EAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,IAAA,gCAAc,EAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,CAAC,IAAA,gCAAc,EAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;YAC9B,MAAM,KAAK,GAAG;gBACZ,gBAAgB,EAAE;oBAChB,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,EAAE,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC,EAAE;iBAChG;gBACD,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC;aAC/D,CAAC;YACF,MAAM,CAAC,IAAA,oCAAkB,EAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,IAAA,oCAAkB,EAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,KAAK,GAAG;gBACZ,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAc;aACpG,CAAC;YACF,MAAM,CAAC,IAAA,oCAAkB,EAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-matrix.test.d.ts","sourceRoot":"","sources":["../../tests/install-matrix.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
const settings_cleanup_js_1 = require("../scripts/lib/settings-cleanup.js");
|
|
10
|
+
const detect_plugin_js_1 = require("../scripts/lib/detect-plugin.js");
|
|
11
|
+
const FIXTURES = path_1.default.join(__dirname, 'fixtures');
|
|
12
|
+
function loadFixture(name) {
|
|
13
|
+
const tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'mindlore-matrix-'));
|
|
14
|
+
const src = path_1.default.join(FIXTURES, name);
|
|
15
|
+
const dest = path_1.default.join(tmpDir, 'settings.json');
|
|
16
|
+
fs_1.default.copyFileSync(src, dest);
|
|
17
|
+
return dest;
|
|
18
|
+
}
|
|
19
|
+
function countMindloreHooks(settingsPath) {
|
|
20
|
+
const settings = JSON.parse(fs_1.default.readFileSync(settingsPath, 'utf8'));
|
|
21
|
+
let count = 0;
|
|
22
|
+
for (const event of Object.keys(settings.hooks ?? {})) {
|
|
23
|
+
for (const entry of settings.hooks[event] ?? []) {
|
|
24
|
+
const hooks = entry.hooks ?? [entry];
|
|
25
|
+
for (const h of hooks) {
|
|
26
|
+
if (/node_modules[/\\]mindlore[/\\]hooks[/\\]/.test(h.command ?? '')) {
|
|
27
|
+
count++;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return count;
|
|
33
|
+
}
|
|
34
|
+
describe('Install Matrix — 4 scenarios', () => {
|
|
35
|
+
describe('Scenario 1: Marketplace-only (clean settings.json)', () => {
|
|
36
|
+
it('no legacy hooks in settings.json — cleanup is no-op', () => {
|
|
37
|
+
const settingsPath = loadFixture('settings-clean.json');
|
|
38
|
+
// Simulate: user only has plugin, never ran npx init
|
|
39
|
+
const before = countMindloreHooks(settingsPath);
|
|
40
|
+
expect(before).toBe(0);
|
|
41
|
+
// Cleanup should do nothing
|
|
42
|
+
const result = (0, settings_cleanup_js_1.cleanupLegacyHooks)(settingsPath);
|
|
43
|
+
expect(result.removed).toBe(0);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe('Scenario 2: npx-only (hooks in settings.json, no plugin)', () => {
|
|
47
|
+
it('gate logic: plugin NOT installed → cleanup does NOT run, hooks stay', () => {
|
|
48
|
+
const settingsPath = loadFixture('settings-with-mindlore-hooks.json');
|
|
49
|
+
const before = countMindloreHooks(settingsPath);
|
|
50
|
+
expect(before).toBe(4);
|
|
51
|
+
// Simulate gate: detectPluginInstalled() returns false → skip cleanup
|
|
52
|
+
const pluginInstalled = false; // npx-only scenario
|
|
53
|
+
if (pluginInstalled) {
|
|
54
|
+
(0, settings_cleanup_js_1.cleanupLegacyHooks)(settingsPath);
|
|
55
|
+
}
|
|
56
|
+
// Hooks must stay — they are the sole source for npx-only users
|
|
57
|
+
const after = countMindloreHooks(settingsPath);
|
|
58
|
+
expect(after).toBe(4);
|
|
59
|
+
});
|
|
60
|
+
it('detectPluginInstalled checks ~/.claude/plugins/cache/mindlore/', () => {
|
|
61
|
+
// This verifies the detection mechanism exists and is callable
|
|
62
|
+
const result = (0, detect_plugin_js_1.detectPluginInstalled)();
|
|
63
|
+
// In test environment with plugin installed, this is true
|
|
64
|
+
// The important thing: function exists and returns boolean
|
|
65
|
+
expect(typeof result).toBe('boolean');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('Scenario 3: Both installed, user runs init (triggers M2)', () => {
|
|
69
|
+
it('cleanup removes legacy hooks — single fire after', () => {
|
|
70
|
+
const settingsPath = loadFixture('settings-with-mindlore-hooks.json');
|
|
71
|
+
// Before: hooks in settings.json (from old npx init)
|
|
72
|
+
const before = countMindloreHooks(settingsPath);
|
|
73
|
+
expect(before).toBe(4);
|
|
74
|
+
// User runs npx mindlore init → triggers idempotent cleanup
|
|
75
|
+
const result = (0, settings_cleanup_js_1.cleanupLegacyHooks)(settingsPath);
|
|
76
|
+
expect(result.removed).toBe(4);
|
|
77
|
+
// After: no legacy hooks — plugin auto-discovery sole source
|
|
78
|
+
const after = countMindloreHooks(settingsPath);
|
|
79
|
+
expect(after).toBe(0);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe('Scenario 4: Upgrade path (npx mindlore upgrade)', () => {
|
|
83
|
+
it('upgrade triggers same cleanup — idempotent', () => {
|
|
84
|
+
const settingsPath = loadFixture('settings-with-mindlore-hooks.json');
|
|
85
|
+
// First upgrade: removes legacy hooks
|
|
86
|
+
const first = (0, settings_cleanup_js_1.cleanupLegacyHooks)(settingsPath);
|
|
87
|
+
expect(first.removed).toBe(4);
|
|
88
|
+
// Second upgrade: idempotent, nothing to remove
|
|
89
|
+
const second = (0, settings_cleanup_js_1.cleanupLegacyHooks)(settingsPath);
|
|
90
|
+
expect(second.removed).toBe(0);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe('Guard: user custom hooks preserved', () => {
|
|
94
|
+
it('does not remove user hooks with mindlore- prefix but custom path', () => {
|
|
95
|
+
const settingsPath = loadFixture('settings-mixed-hooks.json');
|
|
96
|
+
const result = (0, settings_cleanup_js_1.cleanupLegacyHooks)(settingsPath);
|
|
97
|
+
// Only node_modules-path hooks removed
|
|
98
|
+
expect(result.removed).toBe(2);
|
|
99
|
+
// User custom hook with mindlore- prefix but ~/.claude/hooks/ path survives
|
|
100
|
+
const settings = JSON.parse(fs_1.default.readFileSync(settingsPath, 'utf8'));
|
|
101
|
+
const preToolUse = settings.hooks.PreToolUse;
|
|
102
|
+
expect(preToolUse).toHaveLength(2); // bash-guard + user custom
|
|
103
|
+
const commands = preToolUse.flatMap((e) =>
|
|
104
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- test fixture shape */
|
|
105
|
+
(e.hooks ?? [e]).map((h) => h.command ?? ''));
|
|
106
|
+
expect(commands.some((c) => c.includes('mindlore-custom-hook'))).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=install-matrix.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-matrix.test.js","sourceRoot":"","sources":["../../tests/install-matrix.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"latency-budget.test.d.ts","sourceRoot":"","sources":["../../tests/latency-budget.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
describe('latency budget', () => {
|
|
4
|
+
it('HOOK_LATENCY_BUDGETS has entry for all known hooks', () => {
|
|
5
|
+
const common = require('../hooks/lib/mindlore-common.cjs');
|
|
6
|
+
const budgets = common.HOOK_LATENCY_BUDGETS;
|
|
7
|
+
expect(Object.keys(budgets).length).toBe(14);
|
|
8
|
+
expect(budgets['mindlore-session-focus']).toBe(100);
|
|
9
|
+
expect(budgets['mindlore-read-guard']).toBe(30);
|
|
10
|
+
expect(budgets['mindlore-search']).toBe(50);
|
|
11
|
+
});
|
|
12
|
+
it('withTelemetrySync logs budget_exceeded in telemetry', () => {
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const os = require('os');
|
|
16
|
+
const common = require('../hooks/lib/mindlore-common.cjs');
|
|
17
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mindlore-budget-'));
|
|
18
|
+
const telPath = path.join(tmpDir, 'telemetry.jsonl');
|
|
19
|
+
// Override MINDLORE_HOME to use tmp telemetry
|
|
20
|
+
const origHome = process.env.MINDLORE_HOME;
|
|
21
|
+
process.env.MINDLORE_HOME = tmpDir;
|
|
22
|
+
// Slow function that exceeds 30ms budget
|
|
23
|
+
common.withTelemetrySync('mindlore-read-guard', () => {
|
|
24
|
+
const end = Date.now() + 50;
|
|
25
|
+
while (Date.now() < end) { } // busy wait
|
|
26
|
+
});
|
|
27
|
+
process.env.MINDLORE_HOME = origHome;
|
|
28
|
+
if (fs.existsSync(telPath)) {
|
|
29
|
+
const lines = fs.readFileSync(telPath, 'utf8').trim().split('\n');
|
|
30
|
+
const last = JSON.parse(lines[lines.length - 1]);
|
|
31
|
+
expect(last.budget_exceeded).toBe(true);
|
|
32
|
+
expect(last.budget_ms).toBe(30);
|
|
33
|
+
}
|
|
34
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=latency-budget.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"latency-budget.test.js","sourceRoot":"","sources":["../../tests/latency-budget.test.ts"],"names":[],"mappings":";;AAAA,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,MAAM,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,oBAAoB,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAAC;QAE3D,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;QAErD,8CAA8C;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,MAAM,CAAC;QAEnC,yCAAyC;QACzC,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,GAAG,EAAE;YACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,CAAA,CAAC,CAAC,YAAY;QAC1C,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC;QAErC,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-namespace.test.d.ts","sourceRoot":"","sources":["../../tests/mcp-namespace.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
// Mock before import
|
|
10
|
+
const originalCwd = process.cwd;
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
process.cwd = originalCwd;
|
|
13
|
+
delete process.env.MINDLORE_HOME;
|
|
14
|
+
});
|
|
15
|
+
describe('resolveMindloreHome', () => {
|
|
16
|
+
let resolveMindloreHome;
|
|
17
|
+
beforeAll(async () => {
|
|
18
|
+
const mod = await import('../scripts/lib/mcp-namespace.js');
|
|
19
|
+
resolveMindloreHome = mod.resolveMindloreHome;
|
|
20
|
+
});
|
|
21
|
+
it('returns global path even when cwd has .mindlore/', () => {
|
|
22
|
+
const tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'mindlore-test-'));
|
|
23
|
+
const localMindlore = path_1.default.join(tmpDir, '.mindlore');
|
|
24
|
+
fs_1.default.mkdirSync(localMindlore, { recursive: true });
|
|
25
|
+
process.cwd = () => tmpDir;
|
|
26
|
+
const result = resolveMindloreHome();
|
|
27
|
+
expect(result).toBe(path_1.default.join(os_1.default.homedir(), '.mindlore'));
|
|
28
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
29
|
+
});
|
|
30
|
+
it('respects MINDLORE_HOME env var', () => {
|
|
31
|
+
const customDir = path_1.default.join(os_1.default.tmpdir(), 'custom-mindlore-' + Date.now());
|
|
32
|
+
process.env.MINDLORE_HOME = customDir;
|
|
33
|
+
const result = resolveMindloreHome();
|
|
34
|
+
expect(result).toBe(path_1.default.resolve(customDir));
|
|
35
|
+
});
|
|
36
|
+
it('returns ~/.mindlore by default', () => {
|
|
37
|
+
const result = resolveMindloreHome();
|
|
38
|
+
expect(result).toBe(path_1.default.join(os_1.default.homedir(), '.mindlore'));
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=mcp-namespace.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-namespace.test.js","sourceRoot":"","sources":["../../tests/mcp-namespace.test.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AACxB,4CAAoB;AACpB,4CAAoB;AAEpB,qBAAqB;AACrB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;AAEhC,SAAS,CAAC,GAAG,EAAE;IACb,OAAO,CAAC,GAAG,GAAG,WAAW,CAAC;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AACnC,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,IAAI,mBAAiC,CAAC;IAEtC,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;QAC5D,mBAAmB,GAAG,GAAG,CAAC,mBAAmB,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,MAAM,GAAG,YAAE,CAAC,WAAW,CAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACxE,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACrD,YAAE,CAAC,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC;QAE3B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QAE1D,YAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,SAAS,CAAC;QAEtC,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|