mindlore 0.7.0 → 0.7.1

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 (56) hide show
  1. package/README.md +30 -3
  2. package/dist/scripts/bundle-hooks.d.ts +2 -0
  3. package/dist/scripts/bundle-hooks.d.ts.map +1 -0
  4. package/dist/scripts/bundle-hooks.js +68 -0
  5. package/dist/scripts/bundle-hooks.js.map +1 -0
  6. package/dist/scripts/init.js +0 -3
  7. package/dist/scripts/init.js.map +1 -1
  8. package/dist/scripts/lib/constants.d.ts +0 -2
  9. package/dist/scripts/lib/constants.d.ts.map +1 -1
  10. package/dist/scripts/lib/constants.js +0 -21
  11. package/dist/scripts/lib/constants.js.map +1 -1
  12. package/dist/tests/hook-smoke.test.js +1 -1
  13. package/dist/tests/hook-smoke.test.js.map +1 -1
  14. package/dist/tests/search-hook.test.js +1 -1
  15. package/dist/tests/search-hook.test.js.map +1 -1
  16. package/hooks/cc-memory-bulk-sync.cjs +592 -0
  17. package/hooks/cc-session-sync.cjs +842 -0
  18. package/hooks/hooks.json +149 -0
  19. package/hooks/lib/mindlore-common.cjs +2 -2
  20. package/hooks/lib/secure-io.cjs +17 -0
  21. package/hooks/mindlore-cwd-changed.cjs +19 -34
  22. package/hooks/mindlore-decision-detector.cjs +40 -31
  23. package/hooks/mindlore-dont-repeat.cjs +57 -115
  24. package/hooks/mindlore-fts5-sync.cjs +15 -44
  25. package/hooks/mindlore-index.cjs +100 -101
  26. package/hooks/mindlore-model-router.cjs +20 -32
  27. package/hooks/mindlore-post-compact.cjs +26 -42
  28. package/hooks/mindlore-post-read.cjs +35 -60
  29. package/hooks/mindlore-pre-compact.cjs +55 -73
  30. package/hooks/mindlore-read-guard.cjs +28 -51
  31. package/hooks/mindlore-research-guard.cjs +63 -101
  32. package/hooks/mindlore-search.cjs +1142 -93
  33. package/hooks/mindlore-session-end.cjs +155 -276
  34. package/hooks/mindlore-session-focus.cjs +639 -110
  35. package/hooks/src/lib/constants.cjs +15 -0
  36. package/hooks/src/lib/mindlore-common.cjs +975 -0
  37. package/hooks/src/lib/mindlore-common.d.cts +72 -0
  38. package/hooks/src/lib/secure-io.cjs +17 -0
  39. package/hooks/src/lib/types.d.ts +58 -0
  40. package/hooks/src/mindlore-cwd-changed.cjs +57 -0
  41. package/hooks/src/mindlore-decision-detector.cjs +54 -0
  42. package/hooks/src/mindlore-dont-repeat.cjs +222 -0
  43. package/hooks/src/mindlore-fts5-sync.cjs +98 -0
  44. package/hooks/src/mindlore-index.cjs +230 -0
  45. package/hooks/src/mindlore-model-router.cjs +54 -0
  46. package/hooks/src/mindlore-post-compact.cjs +69 -0
  47. package/hooks/src/mindlore-post-read.cjs +106 -0
  48. package/hooks/src/mindlore-pre-compact.cjs +154 -0
  49. package/hooks/src/mindlore-read-guard.cjs +105 -0
  50. package/hooks/src/mindlore-research-guard.cjs +176 -0
  51. package/hooks/src/mindlore-search.cjs +200 -0
  52. package/hooks/src/mindlore-session-end.cjs +511 -0
  53. package/hooks/src/mindlore-session-focus.cjs +256 -0
  54. package/package.json +7 -3
  55. package/plugin.json +3 -3
  56. package/templates/config.json +1 -1
@@ -1,106 +1,81 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * mindlore-post-read — PostToolUse hook (matcher: "Read")
6
- *
7
- * After a file is read, estimate its token count
8
- * and store in _session-reads.json for the read-guard to reference.
9
- *
10
- * Outputs token estimate via additionalContext JSON.
11
- * Also stores token info in _session-reads.json for read-guard.
12
- */
13
-
14
- const fs = require('fs');
15
- const path = require('path');
16
- const { findMindloreDir, getProjectName, hookLog, withTelemetry } = require('./lib/mindlore-common.cjs');
17
-
18
- const CODE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.py', '.rs', '.go', '.java', '.c', '.cpp', '.h', '.css', '.scss', '.sql', '.sh', '.yaml', '.yml', '.json', '.toml', '.xml', '.cjs', '.mjs']);
19
- const PROSE_EXTS = new Set(['.md', '.txt', '.rst', '.adoc']);
20
-
2
+ "use strict";
3
+
4
+ // hooks/src/mindlore-post-read.cjs
5
+ var fs = require("fs");
6
+ var path = require("path");
7
+ var { findMindloreDir, getProjectName, hookLog, withTelemetry } = require("./lib/mindlore-common.cjs");
8
+ var CODE_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".rs", ".go", ".java", ".c", ".cpp", ".h", ".css", ".scss", ".sql", ".sh", ".yaml", ".yml", ".json", ".toml", ".xml", ".cjs", ".mjs"]);
9
+ var PROSE_EXTS = /* @__PURE__ */ new Set([".md", ".txt", ".rst", ".adoc"]);
21
10
  function estimateTokens(charCount, ext) {
22
- const ratio = CODE_EXTS.has(ext) ? 3.5 : PROSE_EXTS.has(ext) ? 4.0 : 3.75;
11
+ const ratio = CODE_EXTS.has(ext) ? 3.5 : PROSE_EXTS.has(ext) ? 4 : 3.75;
23
12
  return Math.ceil(charCount / ratio);
24
13
  }
25
-
26
14
  function main() {
27
15
  const baseDir = findMindloreDir();
28
16
  if (!baseDir) return;
29
-
30
- let input = '';
31
- const stdinTimeout = setTimeout(() => process.exit(0), 3000);
32
- process.stdin.setEncoding('utf8');
33
- process.stdin.on('error', () => process.exit(0));
34
- process.stdin.on('data', chunk => input += chunk);
35
- process.stdin.on('end', () => {
17
+ let input = "";
18
+ const stdinTimeout = setTimeout(() => process.exit(0), 3e3);
19
+ process.stdin.setEncoding("utf8");
20
+ process.stdin.on("error", () => process.exit(0));
21
+ process.stdin.on("data", (chunk) => input += chunk);
22
+ process.stdin.on("end", () => {
36
23
  clearTimeout(stdinTimeout);
37
24
  try {
38
- const data = JSON.parse(input || '{}');
25
+ const data = JSON.parse(input || "{}");
39
26
  const toolInput = data.tool_input || {};
40
27
  const toolOutput = data.tool_output || {};
41
-
42
- const filePath = toolInput.file_path || toolInput.path || '';
28
+ const filePath = toolInput.file_path || toolInput.path || "";
43
29
  if (!filePath) return process.exit(0);
44
-
45
- // Skip .mindlore/ internals
46
30
  const resolved = path.resolve(filePath);
47
31
  if (resolved.startsWith(path.resolve(baseDir))) return process.exit(0);
48
-
49
- // Get content length from tool output or read file
50
32
  let charCount = 0;
51
33
  if (toolOutput.content) {
52
- charCount = typeof toolOutput.content === 'string'
53
- ? toolOutput.content.length
54
- : JSON.stringify(toolOutput.content).length;
34
+ charCount = typeof toolOutput.content === "string" ? toolOutput.content.length : JSON.stringify(toolOutput.content).length;
55
35
  } else {
56
- // Fallback: read file size
57
36
  try {
58
37
  const stat = fs.statSync(resolved);
59
38
  charCount = stat.size;
60
- } catch { return process.exit(0); }
39
+ } catch {
40
+ return process.exit(0);
41
+ }
61
42
  }
62
-
63
43
  if (charCount === 0) return process.exit(0);
64
-
65
44
  const ext = path.extname(filePath).toLowerCase();
66
45
  const tokens = estimateTokens(charCount, ext);
67
-
68
- // Update _session-reads.json with token info
69
- const diaryDir = path.join(baseDir, 'diary');
46
+ const diaryDir = path.join(baseDir, "diary");
70
47
  const readsPath = path.join(diaryDir, `_session-reads-${getProjectName()}.json`);
71
48
  let reads = {};
72
49
  if (fs.existsSync(readsPath)) {
73
- try { reads = JSON.parse(fs.readFileSync(readsPath, 'utf8')); } catch { reads = {}; }
50
+ try {
51
+ reads = JSON.parse(fs.readFileSync(readsPath, "utf8"));
52
+ } catch {
53
+ reads = {};
54
+ }
74
55
  }
75
-
76
56
  const normalizedPath = path.resolve(filePath);
77
57
  const key = normalizedPath;
78
-
79
- if (typeof reads[key] === 'number') {
80
- // Upgrade from old format (just count) to new format (object)
58
+ if (typeof reads[key] === "number") {
81
59
  reads[key] = { count: reads[key], tokens, chars: charCount };
82
- } else if (reads[key] && typeof reads[key] === 'object') {
60
+ } else if (reads[key] && typeof reads[key] === "object") {
83
61
  reads[key].tokens = tokens;
84
62
  reads[key].chars = charCount;
85
63
  } else {
86
64
  reads[key] = { count: 1, tokens, chars: charCount };
87
65
  }
88
-
89
- fs.writeFileSync(readsPath, JSON.stringify(reads, null, 2), 'utf8');
90
-
91
- // Output token estimate to Claude via additionalContext
66
+ fs.writeFileSync(readsPath, JSON.stringify(reads, null, 2), "utf8");
92
67
  const basename = path.basename(filePath);
93
68
  process.stdout.write(JSON.stringify({
94
69
  hookSpecificOutput: {
95
- hookEventName: 'PostToolUse',
96
- additionalContext: `[Mindlore: ${basename} ~${tokens} token (${charCount} char). Edit etmeyeceksen ctx_execute_file kullan.]`
70
+ hookEventName: "PostToolUse",
71
+ additionalContext: `[Mindlore: ${basename} \u2014 ~${tokens} token (${charCount} char). Edit etmeyeceksen ctx_execute_file kullan.]`
97
72
  }
98
73
  }));
99
74
  } catch {
100
- // Silent fail
101
75
  }
102
76
  process.exit(0);
103
77
  });
104
78
  }
105
-
106
- withTelemetry('mindlore-post-read', main).catch(err => { hookLog('post-read', 'error', err?.message ?? String(err)); });
79
+ withTelemetry("mindlore-post-read", main).catch((err) => {
80
+ hookLog("post-read", "error", err?.message ?? String(err));
81
+ });
@@ -1,21 +1,13 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * mindlore-pre-compact — PreCompact hook
6
- *
7
- * Before context compaction:
8
- * 1. Ensure FTS5 index is up to date
9
- * 2. Write pre-compact episode to episodes/ and append log entry
10
- */
11
-
12
- const fs = require('fs');
13
- const path = require('path');
14
- const { findMindloreDir, openDatabase, hookLog, withTelemetry, listSnapshots } = require('./lib/mindlore-common.cjs');
2
+ "use strict";
15
3
 
4
+ // hooks/src/mindlore-pre-compact.cjs
5
+ var fs = require("fs");
6
+ var path = require("path");
7
+ var { findMindloreDir, openDatabase, hookLog, withTelemetry, listSnapshots } = require("./lib/mindlore-common.cjs");
16
8
  function collectRecentEpisodes(baseDir) {
17
9
  try {
18
- const dbPath = path.join(baseDir, 'mindlore.db');
10
+ const dbPath = path.join(baseDir, "mindlore.db");
19
11
  const db = openDatabase(dbPath, { readonly: true });
20
12
  if (!db) return [];
21
13
  try {
@@ -25,11 +17,11 @@ function collectRecentEpisodes(baseDir) {
25
17
  if (episodes.length === 0) return [];
26
18
  const grouped = {};
27
19
  for (const ep of episodes) {
28
- const kind = ep.kind || 'other';
20
+ const kind = ep.kind || "other";
29
21
  if (!grouped[kind]) grouped[kind] = [];
30
22
  grouped[kind].push(ep.summary);
31
23
  }
32
- const lines = ['## Session Episodes'];
24
+ const lines = ["## Session Episodes"];
33
25
  for (const [kind, items] of Object.entries(grouped)) {
34
26
  lines.push(`### ${kind}`);
35
27
  for (const item of items) lines.push(`- ${item}`);
@@ -42,26 +34,26 @@ function collectRecentEpisodes(baseDir) {
42
34
  return [];
43
35
  }
44
36
  }
45
-
46
37
  function collectGitDiff() {
47
38
  try {
48
- const { execFileSync } = require('child_process');
49
- let diffStat = '';
39
+ const { execFileSync } = require("child_process");
40
+ let diffStat = "";
50
41
  try {
51
- diffStat = execFileSync('git', ['diff', '--stat', 'HEAD'], { encoding: 'utf8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
52
- } catch { diffStat = ''; }
53
- if (diffStat) return ['## Changed Files (uncommitted)', '```', diffStat, '```'];
42
+ diffStat = execFileSync("git", ["diff", "--stat", "HEAD"], { encoding: "utf8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
43
+ } catch {
44
+ diffStat = "";
45
+ }
46
+ if (diffStat) return ["## Changed Files (uncommitted)", "```", diffStat, "```"];
54
47
  return [];
55
48
  } catch (_err) {
56
49
  return [];
57
50
  }
58
51
  }
59
-
60
52
  function getActivePlan() {
61
53
  try {
62
- const plansDir = path.join(process.cwd(), '.claude', 'plans');
54
+ const plansDir = path.join(process.cwd(), ".claude", "plans");
63
55
  if (!fs.existsSync(plansDir)) return [];
64
- const plans = fs.readdirSync(plansDir).filter(f => f.endsWith('.md'));
56
+ const plans = fs.readdirSync(plansDir).filter((f) => f.endsWith(".md"));
65
57
  if (plans.length === 0) return [];
66
58
  const latestPlan = plans.sort().pop();
67
59
  return [`## Active Plan: ${latestPlan}`];
@@ -69,86 +61,76 @@ function getActivePlan() {
69
61
  return [];
70
62
  }
71
63
  }
72
-
73
64
  function main() {
74
65
  const baseDir = findMindloreDir();
75
66
  if (!baseDir) return;
76
-
77
- // Trigger FTS5 sync via the index script
78
- const indexScript = path.join(__dirname, '..', 'scripts', 'mindlore-fts5-index.cjs');
67
+ const indexScript = path.join(__dirname, "..", "scripts", "mindlore-fts5-index.cjs");
79
68
  if (fs.existsSync(indexScript)) {
80
69
  try {
81
- const { spawnSync } = require('child_process');
82
- spawnSync('node', [indexScript, baseDir], {
83
- timeout: 10000,
84
- stdio: 'pipe',
85
- windowsHide: true,
70
+ const { spawnSync } = require("child_process");
71
+ spawnSync("node", [indexScript, baseDir], {
72
+ timeout: 1e4,
73
+ stdio: "pipe",
74
+ windowsHide: true
86
75
  });
87
76
  } catch (_err) {
88
- // Non-fatal — index might fail if better-sqlite3 not available
89
77
  }
90
78
  }
91
-
92
- const now = new Date();
79
+ const now = /* @__PURE__ */ new Date();
93
80
  const iso = now.toISOString();
94
- const ts = iso.replace(/[:.]/g, '-');
95
-
96
- const episodesDir = path.join(baseDir, 'episodes');
81
+ const ts = iso.replace(/[:.]/g, "-");
82
+ const episodesDir = path.join(baseDir, "episodes");
97
83
  try {
98
84
  const episodePath = path.join(episodesDir, `pre-compact-${ts}.md`);
99
85
  const content = [
100
- '---',
101
- 'type: episode',
102
- 'subtype: pre-compact',
86
+ "---",
87
+ "type: episode",
88
+ "subtype: pre-compact",
103
89
  `date: ${iso.slice(0, 10)}`,
104
90
  `project: ${path.basename(process.cwd())}`,
105
- '---',
106
- '',
91
+ "---",
92
+ "",
107
93
  `Pre-compact snapshot at ${iso}.`,
108
- `Working directory: ${process.cwd()}`,
109
- ].join('\n');
110
- fs.writeFileSync(episodePath, content, 'utf8');
111
- } catch (_err) { /* episodes dir may not exist */ }
112
-
113
- // Append log entry
114
- const logPath = path.join(baseDir, 'log.md');
94
+ `Working directory: ${process.cwd()}`
95
+ ].join("\n");
96
+ fs.writeFileSync(episodePath, content, "utf8");
97
+ } catch (_err) {
98
+ }
99
+ const logPath = path.join(baseDir, "log.md");
115
100
  try {
116
- const entry = `| ${iso.slice(0, 10)} | pre-compact | FTS5 flush before compaction |\n`;
117
- fs.appendFileSync(logPath, entry, 'utf8');
118
- } catch (_err) { /* log file may not exist */ }
119
-
120
- // Build compaction snapshot (#17)
121
- const diaryDir = path.join(baseDir, 'diary');
101
+ const entry = `| ${iso.slice(0, 10)} | pre-compact | FTS5 flush before compaction |
102
+ `;
103
+ fs.appendFileSync(logPath, entry, "utf8");
104
+ } catch (_err) {
105
+ }
106
+ const diaryDir = path.join(baseDir, "diary");
122
107
  try {
123
108
  const sections = [];
124
109
  sections.push(...collectRecentEpisodes(baseDir));
125
110
  sections.push(...collectGitDiff());
126
111
  sections.push(...getActivePlan());
127
-
128
112
  if (sections.length > 0) {
129
113
  const snapshotContent = [
130
- '---',
131
- 'type: compaction-snapshot',
114
+ "---",
115
+ "type: compaction-snapshot",
132
116
  `date: ${iso.slice(0, 10)}`,
133
117
  `project: ${path.basename(process.cwd())}`,
134
- '---',
135
- '',
136
- ...sections,
137
- ].join('\n');
118
+ "---",
119
+ "",
120
+ ...sections
121
+ ].join("\n");
138
122
  fs.writeFileSync(path.join(diaryDir, `compaction-snapshot-${ts}.md`), snapshotContent);
139
123
  }
140
-
141
- const snapshots = listSnapshots(diaryDir).filter(f => f.startsWith('compaction-'));
124
+ const snapshots = listSnapshots(diaryDir).filter((f) => f.startsWith("compaction-"));
142
125
  while (snapshots.length > 5) {
143
126
  const oldest = snapshots.shift();
144
127
  if (oldest) fs.unlinkSync(path.join(diaryDir, oldest));
145
128
  }
146
- } catch (_err) { /* snapshot is best-effort */ }
147
-
148
- process.stdout.write('[Mindlore: pre-compact FTS5 flush complete]\n');
129
+ } catch (_err) {
130
+ }
131
+ process.stdout.write("[Mindlore: pre-compact FTS5 flush complete]\n");
149
132
  }
150
-
151
- withTelemetry('mindlore-pre-compact', main).catch(err => {
152
- hookLog('mindlore-pre-compact', 'error', err?.message ?? String(err));
133
+ withTelemetry("mindlore-pre-compact", main).catch((err) => {
134
+ hookLog("mindlore-pre-compact", "error", err?.message ?? String(err));
153
135
  process.exit(0);
154
136
  });
@@ -1,60 +1,40 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * mindlore-read-guard — PreToolUse hook (if: "Read")
6
- *
7
- * Repeated-read detection: detects files read multiple times
8
- * in the same session and emits a soft warning.
9
- * Does NOT block (exit 0) — advisory only.
10
- *
11
- * Storage: .mindlore/diary/_session-reads.json
12
- * Cleanup: session-end hook writes stats to delta then deletes the file.
13
- */
14
-
15
- const fs = require('fs');
16
- const path = require('path');
17
- const { findMindloreDir, readHookStdin, getProjectName, hookLog, extractSkeleton, withTelemetrySync } = require('./lib/mindlore-common.cjs');
2
+ "use strict";
18
3
 
4
+ // hooks/src/mindlore-read-guard.cjs
5
+ var fs = require("fs");
6
+ var path = require("path");
7
+ var { findMindloreDir, readHookStdin, getProjectName, hookLog, extractSkeleton, withTelemetrySync } = require("./lib/mindlore-common.cjs");
19
8
  function main() {
20
9
  const baseDir = findMindloreDir();
21
10
  if (!baseDir) return;
22
-
23
- const filePath = readHookStdin(['file_path', 'path']);
11
+ const filePath = readHookStdin(["file_path", "path"]);
24
12
  if (!filePath) return;
25
-
26
- // Only track CWD-relative files, skip .mindlore/ internals
27
13
  const cwd = process.cwd();
28
14
  const resolved = path.resolve(filePath);
29
15
  if (!resolved.startsWith(cwd)) return;
30
16
  if (resolved.startsWith(path.resolve(baseDir))) return;
31
-
32
- // Load or create session reads tracker
33
- const diaryDir = path.join(baseDir, 'diary');
17
+ const diaryDir = path.join(baseDir, "diary");
34
18
  if (!fs.existsSync(diaryDir)) {
35
19
  fs.mkdirSync(diaryDir, { recursive: true });
36
20
  }
37
-
38
21
  const readsPath = path.join(diaryDir, `_session-reads-${getProjectName()}.json`);
39
22
  let reads = {};
40
23
  if (fs.existsSync(readsPath)) {
41
24
  try {
42
- reads = JSON.parse(fs.readFileSync(readsPath, 'utf8'));
25
+ reads = JSON.parse(fs.readFileSync(readsPath, "utf8"));
43
26
  } catch (_err) {
44
27
  reads = {};
45
28
  }
46
29
  }
47
-
48
30
  const normalizedPath = path.resolve(filePath);
49
31
  const existing = reads[normalizedPath];
50
-
51
- // Support both old format (number) and new format (object with tokens)
52
32
  let count, tokens;
53
- if (typeof existing === 'number') {
33
+ if (typeof existing === "number") {
54
34
  count = existing + 1;
55
35
  tokens = 0;
56
36
  reads[normalizedPath] = { count, tokens: 0, chars: 0 };
57
- } else if (existing && typeof existing === 'object') {
37
+ } else if (existing && typeof existing === "object") {
58
38
  count = (existing.count || 0) + 1;
59
39
  tokens = existing.tokens || 0;
60
40
  existing.count = count;
@@ -64,42 +44,39 @@ function main() {
64
44
  tokens = 0;
65
45
  reads[normalizedPath] = { count, tokens: 0, chars: 0 };
66
46
  }
67
-
68
- // Write updated reads
69
- fs.writeFileSync(readsPath, JSON.stringify(reads, null, 2), 'utf8');
70
-
47
+ fs.writeFileSync(readsPath, JSON.stringify(reads, null, 2), "utf8");
71
48
  const basename = path.basename(filePath);
72
- const tokenInfo = tokens > 0 ? ` (~${tokens} token)` : '';
73
-
74
- // Block on 3+ repeated reads (exit 2 = block tool call)
49
+ const tokenInfo = tokens > 0 ? ` (~${tokens} token)` : "";
75
50
  if (count >= 3) {
76
- const totalWaste = tokens > 0 ? ` Toplam israf: ~${tokens * (count - 1)} token.` : '';
51
+ const totalWaste = tokens > 0 ? ` Toplam israf: ~${tokens * (count - 1)} token.` : "";
77
52
  process.stderr.write(`[Mindlore BLOCK] ${basename}${tokenInfo} bu session'da ${count}. kez okunuyor.${totalWaste} Edit icin gerekiyorsa once degisikligini yap, sonra tekrar oku. Analiz icin ctx_execute_file kullan.`);
78
53
  process.exit(2);
79
54
  }
80
-
81
- // Warn on 2nd read (exit 0 = allow but warn)
82
55
  if (count > 1) {
83
- const totalWaste = tokens > 0 ? ` Toplam tekrar: ~${tokens * (count - 1)} token.` : '';
84
- let skeletonSection = '';
56
+ const totalWaste = tokens > 0 ? ` Toplam tekrar: ~${tokens * (count - 1)} token.` : "";
57
+ let skeletonSection = "";
85
58
  try {
86
59
  const ext = path.extname(filePath).slice(1);
87
- const fileContent = fs.readFileSync(filePath, 'utf8');
88
- if (fileContent.length < 500_000) {
60
+ const fileContent = fs.readFileSync(filePath, "utf8");
61
+ if (fileContent.length < 5e5) {
89
62
  const skeleton = extractSkeleton(fileContent, ext);
90
63
  if (skeleton !== fileContent) {
91
- const truncated = skeleton.length > 2000 ? skeleton.slice(0, 2000) + '\n...[truncated]' : skeleton;
92
- skeletonSection = '\n\n' + truncated;
64
+ const truncated = skeleton.length > 2e3 ? skeleton.slice(0, 2e3) + "\n...[truncated]" : skeleton;
65
+ skeletonSection = "\n\n" + truncated;
93
66
  }
94
67
  }
95
- } catch (_e) { /* unreadable/binary — skip */ }
68
+ } catch (_e) {
69
+ }
96
70
  process.stdout.write(JSON.stringify({
97
71
  hookSpecificOutput: {
98
- hookEventName: 'PreToolUse',
99
- additionalContext: `[Mindlore: ${basename}${tokenInfo} bu session'da ${count}. kez okunuyor.${totalWaste} Bir sonraki okuma engellenecek Edit gerekiyorsa simdi yap.]${skeletonSection}`
72
+ hookEventName: "PreToolUse",
73
+ additionalContext: `[Mindlore: ${basename}${tokenInfo} bu session'da ${count}. kez okunuyor.${totalWaste} Bir sonraki okuma engellenecek \u2014 Edit gerekiyorsa simdi yap.]${skeletonSection}`
100
74
  }
101
75
  }));
102
76
  }
103
77
  }
104
-
105
- try { withTelemetrySync('mindlore-read-guard', main); } catch (err) { hookLog('read-guard', 'error', err?.message ?? String(err)); }
78
+ try {
79
+ withTelemetrySync("mindlore-read-guard", main);
80
+ } catch (err) {
81
+ hookLog("read-guard", "error", err?.message ?? String(err));
82
+ }