mindlore 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/scripts/cc-session-sync.d.ts +1 -0
  2. package/dist/scripts/cc-session-sync.d.ts.map +1 -1
  3. package/dist/scripts/cc-session-sync.js +55 -0
  4. package/dist/scripts/cc-session-sync.js.map +1 -1
  5. package/dist/scripts/fetch-raw.js +38 -2
  6. package/dist/scripts/fetch-raw.js.map +1 -1
  7. package/dist/scripts/init.js +47 -43
  8. package/dist/scripts/init.js.map +1 -1
  9. package/dist/scripts/lib/episodes.d.ts +1 -1
  10. package/dist/scripts/lib/episodes.d.ts.map +1 -1
  11. package/dist/scripts/lib/episodes.js +1 -1
  12. package/dist/scripts/lib/episodes.js.map +1 -1
  13. package/dist/scripts/lib/migrations-v062.d.ts +3 -0
  14. package/dist/scripts/lib/migrations-v062.d.ts.map +1 -0
  15. package/dist/scripts/lib/migrations-v062.js +35 -0
  16. package/dist/scripts/lib/migrations-v062.js.map +1 -0
  17. package/dist/scripts/lib/session-payload.d.ts.map +1 -1
  18. package/dist/scripts/lib/session-payload.js +12 -0
  19. package/dist/scripts/lib/session-payload.js.map +1 -1
  20. package/dist/scripts/lib/triage.d.ts +18 -0
  21. package/dist/scripts/lib/triage.d.ts.map +1 -0
  22. package/dist/scripts/lib/triage.js +81 -0
  23. package/dist/scripts/lib/triage.js.map +1 -0
  24. package/dist/scripts/mindlore-doctor.d.ts +1 -0
  25. package/dist/scripts/mindlore-doctor.d.ts.map +1 -1
  26. package/dist/scripts/mindlore-doctor.js +26 -1
  27. package/dist/scripts/mindlore-doctor.js.map +1 -1
  28. package/dist/scripts/mindlore-health-check.d.ts +10 -0
  29. package/dist/scripts/mindlore-health-check.d.ts.map +1 -1
  30. package/dist/scripts/mindlore-health-check.js +26 -1
  31. package/dist/scripts/mindlore-health-check.js.map +1 -1
  32. package/dist/scripts/mindlore-perf.d.ts +3 -3
  33. package/dist/scripts/mindlore-perf.d.ts.map +1 -1
  34. package/dist/scripts/mindlore-perf.js +10 -8
  35. package/dist/scripts/mindlore-perf.js.map +1 -1
  36. package/dist/tests/compaction-snapshot.test.d.ts +2 -0
  37. package/dist/tests/compaction-snapshot.test.d.ts.map +1 -0
  38. package/dist/tests/compaction-snapshot.test.js +55 -0
  39. package/dist/tests/compaction-snapshot.test.js.map +1 -0
  40. package/dist/tests/diary.test.js +3 -3
  41. package/dist/tests/diary.test.js.map +1 -1
  42. package/dist/tests/doctor.test.js +13 -0
  43. package/dist/tests/doctor.test.js.map +1 -1
  44. package/dist/tests/fetch-raw.test.js +12 -5
  45. package/dist/tests/fetch-raw.test.js.map +1 -1
  46. package/dist/tests/health-check-memory.test.js +27 -0
  47. package/dist/tests/health-check-memory.test.js.map +1 -1
  48. package/dist/tests/helpers/db.d.ts.map +1 -1
  49. package/dist/tests/helpers/db.js +3 -1
  50. package/dist/tests/helpers/db.js.map +1 -1
  51. package/dist/tests/init.test.js +20 -0
  52. package/dist/tests/init.test.js.map +1 -1
  53. package/dist/tests/migrations-v062.test.d.ts +2 -0
  54. package/dist/tests/migrations-v062.test.d.ts.map +1 -0
  55. package/dist/tests/migrations-v062.test.js +61 -0
  56. package/dist/tests/migrations-v062.test.js.map +1 -0
  57. package/dist/tests/nomination.test.js +1 -1
  58. package/dist/tests/savings.test.d.ts +2 -0
  59. package/dist/tests/savings.test.d.ts.map +1 -0
  60. package/dist/tests/savings.test.js +87 -0
  61. package/dist/tests/savings.test.js.map +1 -0
  62. package/dist/tests/session-summary.test.d.ts +2 -0
  63. package/dist/tests/session-summary.test.d.ts.map +1 -0
  64. package/dist/tests/session-summary.test.js +102 -0
  65. package/dist/tests/session-summary.test.js.map +1 -0
  66. package/dist/tests/telemetry-perf.test.js +7 -0
  67. package/dist/tests/telemetry-perf.test.js.map +1 -1
  68. package/dist/tests/triage.test.d.ts +2 -0
  69. package/dist/tests/triage.test.d.ts.map +1 -0
  70. package/dist/tests/triage.test.js +69 -0
  71. package/dist/tests/triage.test.js.map +1 -0
  72. package/hooks/lib/mindlore-common.cjs +18 -10
  73. package/hooks/mindlore-post-compact.cjs +23 -3
  74. package/hooks/mindlore-pre-compact.cjs +77 -3
  75. package/hooks/mindlore-session-end.cjs +27 -17
  76. package/hooks/mindlore-session-focus.cjs +104 -68
  77. package/package.json +5 -4
  78. package/plugin.json +1 -1
  79. package/skills/mindlore-maintain/SKILL.md +1 -0
  80. package/templates/config.json +1 -1
@@ -10,23 +10,103 @@
10
10
 
11
11
  const fs = require('fs');
12
12
  const path = require('path');
13
- const { findMindloreDir, readConfig, openDatabase, hasEpisodesTable, querySupersededChains, formatSupersededChains, hookLog, getProjectName, parseFrontmatter, withTelemetry } = require('./lib/mindlore-common.cjs');
13
+ const { findMindloreDir, readConfig, openDatabase, hasEpisodesTable, querySupersededChains, formatSupersededChains, hookLog, getProjectName, parseFrontmatter, withTelemetry, withTimeoutDb } = require('./lib/mindlore-common.cjs');
14
+
15
+ function isCorruptionError(err) {
16
+ const code = err?.code ?? '';
17
+ const msg = String(err?.message ?? err);
18
+ return code === 'SQLITE_CORRUPT' || code === 'SQLITE_NOTADB' || /corrupt|malformed/i.test(msg);
19
+ }
20
+
21
+ function recoverCorruptDb(db, dbPath, reason) {
22
+ try { db.close(); } catch { /* already closed */ }
23
+ const bakPath = dbPath + '.corrupt.bak';
24
+ try { fs.copyFileSync(dbPath, bakPath); } catch { /* best effort */ }
25
+ try { fs.unlinkSync(dbPath); } catch { /* best effort */ }
26
+ hookLog('session-focus', 'warn', reason);
27
+ }
28
+
29
+ function tryOpenDb(dbPath) {
30
+ return openDatabase(dbPath, { readonly: true });
31
+ }
32
+
33
+ function loadDbContent(db, baseDir, config, output, timings) {
34
+ // Session payload: Session summary, Decisions, Friction, Learnings
35
+ const tPayload = Date.now();
36
+ try {
37
+ const { buildSessionPayload } = require('../dist/scripts/lib/session-payload.js');
38
+ const project = path.basename(process.cwd());
39
+ const payloadBudget = config?.tokenBudget?.sessionInject ?? 2000;
40
+ const payload = buildSessionPayload(db, baseDir, project, payloadBudget);
41
+ if (!payload.skipInjection) {
42
+ for (const section of payload.sections) {
43
+ output.push(`[Mindlore ${section.label}]\n${section.content}`);
44
+ }
45
+ }
46
+ } catch (_payloadErr) {
47
+ // Session payload is optional — don't break session start
48
+ }
49
+ timings.db_payload = Date.now() - tPayload;
50
+
51
+ // Supersedes chain display
52
+ const tSuperseded = Date.now();
53
+ if (hasEpisodesTable(db)) {
54
+ const project = path.basename(process.cwd());
55
+
56
+ const chains = querySupersededChains(db, { project, days: 7, limit: 5 });
57
+ if (chains.length > 0) {
58
+ output.push(`[Mindlore Supersedes]\n${formatSupersededChains(chains)}`);
59
+ }
60
+
61
+ // Episode consolidation reminder
62
+ try {
63
+ const rawCount = withTimeoutDb(db,
64
+ "SELECT COUNT(*) as cnt FROM episodes WHERE consolidation_status = 'raw' OR consolidation_status IS NULL",
65
+ [], { mode: 'get' });
66
+ const cnt = rawCount?.cnt ?? 0;
67
+ const consolThreshold = config?.consolidation?.threshold ?? 50;
68
+ if (cnt >= consolThreshold) {
69
+ output.push(`[Mindlore] ${cnt} raw episode birikti — \`/mindlore-maintain consolidate\` ile birleştirmeyi düşün.`);
70
+ }
71
+ } catch (_err) { /* consolidation_status column may not exist yet */ }
72
+ }
73
+ timings.db_episodes = Date.now() - tSuperseded;
74
+
75
+ // Stale content check
76
+ const tStale = Date.now();
77
+ try {
78
+ const thirtyDaysAgo = new Date(Date.now() - (30 * 24 * 60 * 60 * 1000)).toISOString();
79
+ const row = withTimeoutDb(db, 'SELECT COUNT(*) as cnt FROM file_hashes WHERE last_indexed < ?', [thirtyDaysAgo], { mode: 'get' });
80
+ const staleCount = row?.cnt ?? 0;
81
+ if (staleCount > 3) {
82
+ output.push(`[Mindlore: ${staleCount} dosya 30+ gundur guncellenmemis — \`/mindlore-evolve\` dusun]`);
83
+ }
84
+ } catch (_staleErr) { /* file_hashes may not exist */ }
85
+ timings.db_stale = Date.now() - tStale;
86
+ }
14
87
 
15
88
  function main() {
89
+ const t0 = Date.now();
16
90
  const baseDir = findMindloreDir();
17
91
  if (!baseDir) return; // No .mindlore/ found, silently skip
18
92
 
19
93
  const output = [];
20
94
  const config = readConfig(baseDir);
95
+ const timings = {};
96
+ let sourceChars = 0;
21
97
 
22
98
  // Inject INDEX.md
99
+ const tIndex = Date.now();
23
100
  const indexPath = path.join(baseDir, 'INDEX.md');
24
101
  if (fs.existsSync(indexPath)) {
102
+ sourceChars += fs.statSync(indexPath).size;
25
103
  const content = fs.readFileSync(indexPath, 'utf8').trim();
26
104
  output.push(`[Mindlore INDEX]\n${content}`);
27
105
  }
106
+ timings.index_read = Date.now() - tIndex;
28
107
 
29
108
  // Inject latest delta + reflect trigger (single readdirSync)
109
+ const tDiary = Date.now();
30
110
  const diaryDir = path.join(baseDir, 'diary');
31
111
  if (fs.existsSync(diaryDir)) {
32
112
  try {
@@ -36,6 +116,7 @@ function main() {
36
116
  const sorted = [...diaryFiles].sort();
37
117
  const latestName = sorted[sorted.length - 1];
38
118
  const latestPath = path.join(diaryDir, latestName);
119
+ sourceChars += fs.statSync(latestPath).size;
39
120
  const deltaContent = fs.readFileSync(latestPath, 'utf8').trim();
40
121
  const { meta } = parseFrontmatter(deltaContent);
41
122
  const deltaProject = meta.project || null;
@@ -52,8 +133,10 @@ function main() {
52
133
  }
53
134
  } catch (_err) { /* skip */ }
54
135
  }
136
+ timings.diary_walk = Date.now() - tDiary;
55
137
 
56
138
  // Version check: compare .version (installed) vs .pkg-version (package)
139
+ const tVersion = Date.now();
57
140
  // Both are flat strings written by init — no JSON parse needed on session start
58
141
  const versionPath = path.join(baseDir, '.version');
59
142
  const pkgVersionPath = path.join(baseDir, '.pkg-version');
@@ -66,87 +149,36 @@ function main() {
66
149
  }
67
150
  }
68
151
  } catch (_err) { /* skip */ }
152
+ timings.version_check = Date.now() - tVersion;
69
153
 
70
154
  // v0.5.4: Consolidated session payload (replaces scattered episodes/activity/alerts injection)
155
+ const tDb = Date.now();
156
+ const outputLenBeforeDb = output.reduce((s, o) => s + o.length, 0);
71
157
  try {
72
158
  const dbPath = path.join(baseDir, 'mindlore.db');
73
- const db = openDatabase(dbPath, { readonly: true });
159
+ const tDbOpen = Date.now();
160
+ const db = tryOpenDb(dbPath);
161
+ timings.db_open = Date.now() - tDbOpen;
162
+ timings.db_integrity = 0;
74
163
 
75
164
  if (db) {
76
- // v0.6.1: Integrity check — auto-recover corrupt DB
77
- const recoverCorruptDb = (reason) => {
78
- db.close();
79
- const bakPath = dbPath + '.corrupt.bak';
80
- try { fs.copyFileSync(dbPath, bakPath); } catch { /* best effort */ }
81
- try { fs.unlinkSync(dbPath); } catch { /* best effort */ }
82
- hookLog('session-focus', 'warn', reason);
83
- if (output.length > 0) process.stdout.write(output.join('\n\n'));
84
- };
85
165
  try {
86
- const check = db.pragma('integrity_check(1)');
87
- const result = Array.isArray(check) ? check[0]?.integrity_check : check;
88
- if (result !== 'ok') {
89
- recoverCorruptDb(`Corrupt DB detected, backed up. Run 'npm run index' to rebuild.`);
90
- return;
91
- }
166
+ loadDbContent(db, baseDir, config, output, timings);
92
167
  } catch (err) {
93
- recoverCorruptDb(`DB integrity check failed: ${err.message}`);
94
- return;
95
- }
96
- try {
97
- // Session payload: Session summary, Decisions, Friction, Learnings
98
- try {
99
- const { buildSessionPayload } = require('../dist/scripts/lib/session-payload.js');
100
- const project = path.basename(process.cwd());
101
- const payloadBudget = config?.tokenBudget?.sessionInject ?? 2000;
102
- const payload = buildSessionPayload(db, baseDir, project, payloadBudget);
103
- if (!payload.skipInjection) {
104
- for (const section of payload.sections) {
105
- output.push(`[Mindlore ${section.label}]\n${section.content}`);
106
- }
107
- }
108
- } catch (_payloadErr) {
109
- // Session payload is optional — don't break session start
168
+ if (isCorruptionError(err)) {
169
+ recoverCorruptDb(db, dbPath, `Corrupt DB detected during query: ${err?.message ?? err}`);
110
170
  }
111
-
112
- // v0.4.1: Supersedes chain display (kept — not covered by session-payload)
113
- if (hasEpisodesTable(db)) {
114
- const project = path.basename(process.cwd());
115
-
116
- const chains = querySupersededChains(db, { project, days: 7, limit: 5 });
117
- if (chains.length > 0) {
118
- output.push(`[Mindlore Supersedes]\n${formatSupersededChains(chains)}`);
119
- }
120
-
121
- // v0.5.3: Episode consolidation reminder (kept — threshold-based reminder)
122
- try {
123
- const rawCount = db.prepare(
124
- "SELECT COUNT(*) as cnt FROM episodes WHERE consolidation_status = 'raw' OR consolidation_status IS NULL"
125
- ).get();
126
- const cnt = rawCount?.cnt ?? 0;
127
- const consolThreshold = config?.consolidation?.threshold ?? 50;
128
- if (cnt >= consolThreshold) {
129
- output.push(`[Mindlore] ${cnt} raw episode birikti — \`/mindlore-maintain consolidate\` ile birleştirmeyi düşün.`);
130
- }
131
- } catch (_err) { /* consolidation_status column may not exist yet */ }
132
- }
133
-
134
- // v0.5.5: Stale content check (reuses open DB handle)
135
- try {
136
- const thirtyDaysAgo = new Date(Date.now() - (30 * 24 * 60 * 60 * 1000)).toISOString();
137
- const row = db.prepare('SELECT COUNT(*) as cnt FROM file_hashes WHERE last_indexed < ?').get(thirtyDaysAgo);
138
- const staleCount = row?.cnt ?? 0;
139
- if (staleCount > 3) {
140
- output.push(`[Mindlore: ${staleCount} dosya 30+ gundur guncellenmemis — \`/mindlore-evolve\` dusun]`);
141
- }
142
- } catch (_staleErr) { /* file_hashes may not exist */ }
143
171
  } finally {
144
- db.close();
172
+ try { db.close(); } catch { /* already closed by recovery */ }
145
173
  }
146
174
  }
147
175
  } catch (_err) { /* graceful skip */ }
176
+ const outputLenAfterDb = output.reduce((s, o) => s + o.length, 0);
177
+ sourceChars += (outputLenAfterDb - outputLenBeforeDb);
178
+ timings.db_total = Date.now() - tDb;
148
179
 
149
- hookLog('session-focus', 'info', 'session started');
180
+ timings.total = Date.now() - t0;
181
+ hookLog('session-focus', 'info', `timings: ${JSON.stringify(timings)}`);
150
182
 
151
183
  // Token budget for session inject
152
184
  // Defaults match DEFAULT_TOKEN_BUDGET in scripts/lib/constants.ts
@@ -163,6 +195,10 @@ function main() {
163
195
  if (joined.length > 0) {
164
196
  process.stdout.write(joined + '\n');
165
197
  }
198
+
199
+ const inject_tokens = Math.ceil(joined.length / 4);
200
+ const source_tokens = Math.ceil(sourceChars / 4);
201
+ return { inject_tokens, source_tokens };
166
202
  }
167
203
 
168
204
  withTelemetry('mindlore-session-focus', main).catch(err => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindlore",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "AI-native knowledge system for Claude Code",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -22,7 +22,8 @@
22
22
  "cc-sync": "node dist/scripts/cc-memory-bulk-sync.js",
23
23
  "cleanup": "node dist/scripts/maintain-cleanup.js",
24
24
  "perf": "node dist/scripts/mindlore-perf.js",
25
- "doctor": "node dist/scripts/mindlore-doctor.js"
25
+ "doctor": "node dist/scripts/mindlore-doctor.js",
26
+ "audit": "npm audit --audit-level=moderate"
26
27
  },
27
28
  "keywords": [
28
29
  "claude-code",
@@ -52,12 +53,12 @@
52
53
  "zod": "^4.3.6"
53
54
  },
54
55
  "devDependencies": {
56
+ "@huggingface/transformers": "^4.2.0",
55
57
  "@types/better-sqlite3": "^7.6.13",
56
58
  "@types/jest": "^30.0.0",
57
59
  "@types/node": "^25.6.0",
58
- "@typescript-eslint/eslint-plugin": "^8.58.1",
60
+ "@typescript-eslint/eslint-plugin": "^8.59.0",
59
61
  "@typescript-eslint/parser": "^8.58.1",
60
- "@huggingface/transformers": "^4.2.0",
61
62
  "eslint": "^10.2.0",
62
63
  "globals": "^17.5.0",
63
64
  "jest": "^30.3.0",
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mindlore",
3
3
  "description": "AI-native knowledge system for Claude Code. Persistent, searchable, evolving knowledge base with FTS5.",
4
- "version": "0.6.1",
4
+ "version": "0.6.2",
5
5
  "skills": [
6
6
  {
7
7
  "name": "mindlore-ingest",
@@ -24,6 +24,7 @@ KB bakım skill'i. Reflect düşünür, maintain temizler.
24
24
  - `/mindlore-maintain decay` — stale doc listesi + archive flow
25
25
  - `/mindlore-maintain consolidate` — episode gruplama + dosyaya promote
26
26
  - `/mindlore-maintain contradictions` — çelişki analizi
27
+ - `/mindlore-maintain triage` — unpromoted raw dosyaları listele + metadata göster
27
28
 
28
29
  ## Decay Mode
29
30
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.1",
2
+ "version": "0.6.2",
3
3
  "models": {
4
4
  "ingest": "haiku",
5
5
  "evolve": "sonnet",