@hir4ta/mneme 0.23.2 → 0.24.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mneme",
3
3
  "description": "A plugin that provides long-term memory for Claude Code. It automatically saves context lost during auto-compact, offering features for session restoration, recording technical decisions, and learning developer patterns.",
4
- "version": "0.23.2",
4
+ "version": "0.24.1",
5
5
  "author": {
6
6
  "name": "hir4ta"
7
7
  },
package/README.ja.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mneme
2
2
 
3
- ![Version](https://img.shields.io/badge/version-0.23.2-blue)
3
+ ![Version](https://img.shields.io/badge/version-0.24.1-blue)
4
4
  ![Node.js](https://img.shields.io/badge/node-%3E%3D22.5.0-brightgreen)
5
5
  [![NPM Version](https://img.shields.io/npm/v/%40hir4ta%2Fmneme)](https://www.npmjs.com/package/@hir4ta/mneme)
6
6
  [![MIT License](https://img.shields.io/npm/l/%40hir4ta%2Fmneme)](https://github.com/hir4ta/mneme/blob/main/LICENSE)
@@ -13,14 +13,16 @@ Claude Codeの長期記憶を実現するプラグイン
13
13
 
14
14
  - **インクリメンタル保存**: 各ターン完了時に差分のみをSQLiteに保存(Node.js、高速)
15
15
  - **自動記憶検索**: プロンプトごとに関連する過去のセッション・判断を自動で注入
16
+ - **プログレッシブ検索**: 3層検索(コンパクト → サマリー → フル)でトークン消費を約70%削減
16
17
  - **PreCompact対応**: Auto-Compact前に未保存分をキャッチアップ(コンテキスト95%で発動)
17
18
  - **フルデータ抽出**: `/mneme:save` で要約・判断・パターン・ルールを一括保存
18
19
  - **セッション再開**: `/mneme:resume` で過去のセッションを再開(チェーン追跡付き)
19
- - **セッション提案**: セッション開始時に最新3件を提案
20
+ - **ナレッジ・リフレクション**: `/mneme:reflect` で蓄積された知見を横断分析 — パターン検出、矛盾発見、鮮度チェック、昇格候補の提案
20
21
  - **知見の抽出**: `/mneme:harvest` でPRコメントから decision/pattern/rule の元データを抽出
21
- - **Webダッシュボード**: セッション・元データ・開発ルールの閲覧
22
- - **開発ルール + 承認**: 意思決定・パターン・ルールから開発ルールを生成し、インラインで承認/却下
23
- - **知識グラフ層**: セッションと承認済み開発ルールを一つのグラフで可視化
22
+ - **Webダッシュボード**: セッション、開発ルール、統計、ナレッジグラフ、チーム活動を一括管理
23
+ - **ナレッジグラフ**: 共有タグだけでなく、セッション→判断→パターン→ルールの実際の関係性を可視化
24
+ - **チーム活動**: メンバーごとのセッション数、判断、パターンの貢献度とナレッジ品質を追跡
25
+ - **AIナレッジレポート**: チーム貢献、活動分析、バイリンガル出力(EN/JA)を含むリッチHTMLレポート
24
26
 
25
27
  ## 課題と解決
26
28
 
@@ -114,7 +116,9 @@ Claude Codeを再起動
114
116
  | `/mneme:save` | 全データ抽出: 要約・判断・パターン・ルール |
115
117
  | `/mneme:resume [id]` | セッションを再開(ID省略で一覧表示) |
116
118
  | `/mneme:search "クエリ"` | セッションと承認済み開発ルールを検索 |
119
+ | `/mneme:reflect` | ナレッジ健全性分析: 矛盾検出、鮮度チェック、昇格候補 |
117
120
  | `/mneme:harvest <PR URL>` | PRレビューコメントから知見を抽出 |
121
+ | `/mneme:report` | AI生成のHTMLナレッジレポートを出力 |
118
122
 
119
123
  ### 推奨ワークフロー
120
124
 
@@ -123,9 +127,8 @@ implement → save → approve rules
123
127
  ```
124
128
 
125
129
  1. **implement**: コードを実装
126
- 2. **save**: 元データを抽出して開発ルール候補を生成
127
- 3. **validate**: `npm run validate:sources` で必須項目/priority/tags を検証
128
- 4. **approve rules**: 生成された開発ルールをインラインで確認・承認/却下
130
+ 2. **save**: 元データを抽出して開発ルール候補を生成(バリデーションはMCP経由で自動実行)
131
+ 3. **approve rules**: 生成された開発ルールをインラインで確認・承認/却下
129
132
 
130
133
  ランタイム詳細(Hook分岐、未保存終了、Auto-Compact)は以下:
131
134
  - `docs/mneme-runtime-flow.md`
@@ -151,7 +154,8 @@ npx @hir4ta/mneme --dashboard --port 8080
151
154
  - **Sessions**: セッション一覧・詳細
152
155
  - **開発ルール**: 意思決定・パターン・ルールから生成されたルールの確認・承認
153
156
  - **Statistics**: アクティビティチャート・セッション統計の表示
154
- - **Graph**: タグ共有によるセッション関連性の可視化
157
+ - **Graph**: エンティティ間の関係性(セッション→判断→パターン→ルール)をインタラクティブに可視化
158
+ - **Team**: メンバー貢献度、日別アクティビティ、ナレッジ品質を追跡
155
159
 
156
160
  #### 言語切り替え
157
161
 
@@ -206,6 +210,21 @@ DecisionとPatternは**排他的**です — 同じ知見はどちらか一方
206
210
 
207
211
  > **ヒント**: CLAUDE.md は簡潔に。各行について「これを消したらClaudeがミスするか?」と問い、不要なら削除してください。([ベストプラクティス - Claude Code Docs](https://code.claude.com/docs/en/best-practices))
208
212
 
213
+ ### ナレッジ・リフレクション
214
+
215
+ 蓄積されたナレッジの健全性、矛盾、成長機会を分析します。ナレッジベースの状態を確認したいときに手動で実行してください。
216
+
217
+ ```
218
+ /mneme:reflect
219
+ ```
220
+
221
+ 分析カテゴリ:
222
+ - **繰り返しテーマ**: セッション・判断・パターン横断で出現するタグと知識密度スコア
223
+ - **矛盾検出**: 相反する可能性のあるアクティブな判断(AIによる意味的分析)
224
+ - **昇格候補**: ルールに昇格されていない承認済みパターン
225
+ - **鮮度チェック**: 更新されていない古い判断、未使用のルール、放置されたドラフト
226
+ - **ナレッジ健全性**: 全体統計、承認パイプライン、優先度分布、タグカバレッジ
227
+
209
228
  ### ナレッジレポート
210
229
 
211
230
  Claude Code がセッションデータを分析し、開発活動の要約・セッションタイムライン・ナレッジハイライト・活用状況を含むリッチなHTMLレポートを生成します。
@@ -217,6 +236,7 @@ Claude Code がセッションデータを分析し、開発活動の要約・
217
236
  機能:
218
237
  - 期間選択: 1週間(デフォルト)、2週間、1ヶ月
219
238
  - AI生成の開発活動サマリー
239
+ - チーム貢献の内訳(メンバーごとのセッション数・判断・パターン)
220
240
  - 展開可能なセッションタイムライン(目標、成果、議論、エラー)
221
241
  - ナレッジハイライト(意思決定・パターン・ルール)を直接表示
222
242
  - 全ソースからのタグヒートマップ
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mneme
2
2
 
3
- ![Version](https://img.shields.io/badge/version-0.23.2-blue)
3
+ ![Version](https://img.shields.io/badge/version-0.24.1-blue)
4
4
  ![Node.js](https://img.shields.io/badge/node-%3E%3D22.5.0-brightgreen)
5
5
  [![NPM Version](https://img.shields.io/npm/v/%40hir4ta%2Fmneme)](https://www.npmjs.com/package/@hir4ta/mneme)
6
6
  [![MIT License](https://img.shields.io/npm/l/%40hir4ta%2Fmneme)](https://github.com/hir4ta/mneme/blob/main/LICENSE)
@@ -13,14 +13,16 @@ Provides automatic session saving, intelligent memory search, and web dashboard
13
13
 
14
14
  - **Incremental save**: Save only new interactions on each turn completion (Node.js, fast)
15
15
  - **Auto memory search**: Related past sessions/decisions automatically injected on each prompt
16
+ - **Progressive search**: 3-layer search (compact → summary → full) that reduces token usage by ~70%
16
17
  - **PreCompact support**: Catch up unsaved interactions before Auto-Compact (context 95% full)
17
18
  - **Full data extraction**: Save summary, decisions, patterns, and rules with `/mneme:save`
18
19
  - **Session Resume**: Resume past sessions with `/mneme:resume` (with chain tracking)
19
- - **Session Suggestion**: Recent 3 sessions shown at session start
20
+ - **Knowledge Reflection**: Analyze accumulated knowledge to detect patterns, contradictions, stale items, and promotion candidates with `/mneme:reflect`
20
21
  - **Knowledge Harvesting**: Extract decision/pattern/rule sources from PR comments with `/mneme:harvest`
21
- - **Web Dashboard**: View sessions, source artifacts, and development rules
22
- - **Development Rules + Approval**: Generate rules from decisions/patterns/rules and approve/reject inline
23
- - **Knowledge Graph Layer**: Visualize sessions and approved development rules as one graph
22
+ - **Web Dashboard**: Sessions, development rules, statistics, knowledge graph, and team activity
23
+ - **Knowledge Graph**: Visualize cross-entity relationships session chains, decision origins, pattern sources — not just shared tags
24
+ - **Team Activity**: See who contributed what session counts, decisions, patterns per member, and knowledge quality metrics
25
+ - **AI Knowledge Report**: Rich HTML report with team contributions, activity analysis, and bilingual output (EN/JA)
24
26
 
25
27
  ## Problems Solved
26
28
 
@@ -114,7 +116,9 @@ This will auto-update on Claude Code startup.
114
116
  | `/mneme:save` | Extract all data: summary, decisions, patterns, rules |
115
117
  | `/mneme:resume [id]` | Resume session (show list if ID omitted) |
116
118
  | `/mneme:search "query"` | Search sessions and approved development rules |
119
+ | `/mneme:reflect` | Analyze knowledge health: contradictions, stale items, promotion candidates |
117
120
  | `/mneme:harvest <PR URL>`| Extract knowledge from PR review comments |
121
+ | `/mneme:report` | Generate AI-powered HTML knowledge report |
118
122
 
119
123
  ### Recommended Workflow
120
124
 
@@ -123,9 +127,8 @@ implement → save → approve rules
123
127
  ```
124
128
 
125
129
  1. **implement**: Write code
126
- 2. **save**: Extract source knowledge and generate development rule candidates
127
- 3. **validate**: Run `npm run validate:sources` to enforce required fields/priority/tags
128
- 4. **approve rules**: Review and approve/reject generated development rules inline
130
+ 2. **save**: Extract source knowledge and generate development rule candidates (validation runs automatically via MCP)
131
+ 3. **approve rules**: Review and approve/reject generated development rules inline
129
132
 
130
133
  Detailed runtime flow (hooks, uncommitted policy, auto-compact path):
131
134
  - `docs/mneme-runtime-flow.md`
@@ -151,7 +154,8 @@ npx @hir4ta/mneme --dashboard --port 8080
151
154
  - **Sessions**: List and view sessions
152
155
  - **Development Rules**: Review and approve rules generated from decisions/patterns/rules
153
156
  - **Statistics**: View activity charts and session statistics
154
- - **Graph**: Visualize session connections by shared tags
157
+ - **Graph**: Visualize cross-entity relationships (session decision pattern → rule) with interactive filters
158
+ - **Team**: Track team member contributions, daily activity timeline, and knowledge quality metrics
155
159
 
156
160
  #### Language Switching
157
161
 
@@ -206,6 +210,21 @@ For teams, you can create `.claude/rules/mneme.md` with path-scoped rules:
206
210
 
207
211
  > **Tip**: Keep CLAUDE.md concise. For each line, ask: "Would removing this cause Claude to make mistakes?" If not, cut it. ([Best Practices - Claude Code Docs](https://code.claude.com/docs/en/best-practices))
208
212
 
213
+ ### Knowledge Reflection
214
+
215
+ Analyze your accumulated knowledge for health, contradictions, and growth opportunities. Run manually when you want to review the state of your knowledge base.
216
+
217
+ ```
218
+ /mneme:reflect
219
+ ```
220
+
221
+ Analysis categories:
222
+ - **Recurring themes**: Tags appearing across sessions, decisions, and patterns — with knowledge density scoring
223
+ - **Contradiction detection**: Active decisions that may conflict with each other (AI-powered semantic analysis)
224
+ - **Promotion candidates**: Approved patterns not yet promoted to rules
225
+ - **Staleness check**: Old decisions never updated, unused rules, forgotten drafts
226
+ - **Knowledge health**: Overall stats, approval pipeline, priority distribution, tag coverage
227
+
209
228
  ### Knowledge Report
210
229
 
211
230
  Generate an AI-powered knowledge report. Claude Code analyzes session data and produces a rich HTML report with narrative summaries, session timelines, knowledge highlights, and usage insights.
@@ -217,6 +236,7 @@ Generate an AI-powered knowledge report. Claude Code analyzes session data and p
217
236
  Features:
218
237
  - Choose period: 1 week (default), 2 weeks, or 1 month
219
238
  - AI-generated development activity summary
239
+ - Team contribution breakdown (per-member sessions, decisions, patterns)
220
240
  - Expandable session timeline with goals, outcomes, discussions, and errors
221
241
  - Knowledge highlights (decisions, patterns, rules) displayed directly
222
242
  - Tag heatmap aggregated from all sources
@@ -56,13 +56,13 @@ async function getGitInfo(projectPath) {
56
56
  return { owner, repository, repositoryUrl, repositoryRoot };
57
57
  }
58
58
  function resolveMnemeSessionId(projectPath, claudeSessionId) {
59
- const shortId = claudeSessionId.slice(0, 8);
60
- const sessionLinkPath = path.join(
61
- projectPath,
62
- ".mneme",
63
- "session-links",
64
- `${shortId}.json`
59
+ const sessionLinksDir = path.join(projectPath, ".mneme", "session-links");
60
+ const fullPath = path.join(sessionLinksDir, `${claudeSessionId}.json`);
61
+ const shortPath = path.join(
62
+ sessionLinksDir,
63
+ `${claudeSessionId.slice(0, 8)}.json`
65
64
  );
65
+ const sessionLinkPath = fs.existsSync(fullPath) ? fullPath : shortPath;
66
66
  if (fs.existsSync(sessionLinkPath)) {
67
67
  try {
68
68
  const link = JSON.parse(fs.readFileSync(sessionLinkPath, "utf8"));
@@ -72,24 +72,29 @@ function resolveMnemeSessionId(projectPath, claudeSessionId) {
72
72
  } catch {
73
73
  }
74
74
  }
75
- return shortId;
75
+ return claudeSessionId;
76
76
  }
77
77
  function findSessionFileById(projectPath, mnemeSessionId) {
78
78
  const sessionsDir = path.join(projectPath, ".mneme", "sessions");
79
- const searchDir = (dir) => {
79
+ const searchDirFor = (dir, fileName) => {
80
80
  if (!fs.existsSync(dir)) return null;
81
81
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
82
82
  const fullPath = path.join(dir, entry.name);
83
83
  if (entry.isDirectory()) {
84
- const result = searchDir(fullPath);
85
- if (result) return result;
86
- } else if (entry.name === `${mnemeSessionId}.json`) {
84
+ const result2 = searchDirFor(fullPath, fileName);
85
+ if (result2) return result2;
86
+ } else if (entry.name === fileName) {
87
87
  return fullPath;
88
88
  }
89
89
  }
90
90
  return null;
91
91
  };
92
- return searchDir(sessionsDir);
92
+ const result = searchDirFor(sessionsDir, `${mnemeSessionId}.json`);
93
+ if (result) return result;
94
+ if (mnemeSessionId.length > 8) {
95
+ return searchDirFor(sessionsDir, `${mnemeSessionId.slice(0, 8)}.json`);
96
+ }
97
+ return null;
93
98
  }
94
99
  function hasSessionSummary(sessionFile) {
95
100
  if (!sessionFile) return false;
@@ -181,12 +186,19 @@ function cleanupStaleUncommittedSessions(projectPath, graceDays) {
181
186
  } catch {
182
187
  }
183
188
  }
184
- const linkPath = path2.join(
189
+ const fullLinkPath = path2.join(
190
+ projectPath,
191
+ ".mneme",
192
+ "session-links",
193
+ `${row.claude_session_id}.json`
194
+ );
195
+ const shortLinkPath = path2.join(
185
196
  projectPath,
186
197
  ".mneme",
187
198
  "session-links",
188
199
  `${row.claude_session_id.slice(0, 8)}.json`
189
200
  );
201
+ const linkPath = fs2.existsSync(fullLinkPath) ? fullLinkPath : shortLinkPath;
190
202
  if (fs2.existsSync(linkPath)) {
191
203
  try {
192
204
  fs2.unlinkSync(linkPath);
@@ -322,6 +334,24 @@ function migrateDatabase(db) {
322
334
  `);
323
335
  console.error("[mneme] Migrated: created session_save_state table");
324
336
  }
337
+ try {
338
+ db.exec("SELECT 1 FROM file_index LIMIT 1");
339
+ } catch {
340
+ db.exec(`
341
+ CREATE TABLE IF NOT EXISTS file_index (
342
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
343
+ session_id TEXT NOT NULL,
344
+ project_path TEXT NOT NULL,
345
+ file_path TEXT NOT NULL,
346
+ tool_name TEXT,
347
+ timestamp TEXT NOT NULL,
348
+ created_at TEXT DEFAULT (datetime('now'))
349
+ );
350
+ CREATE INDEX IF NOT EXISTS idx_file_index_session ON file_index(session_id);
351
+ CREATE INDEX IF NOT EXISTS idx_file_index_project_file ON file_index(project_path, file_path);
352
+ `);
353
+ console.error("[mneme] Migrated: created file_index table");
354
+ }
325
355
  }
326
356
  function initDatabase(dbPath) {
327
357
  const mnemeDir = path3.dirname(dbPath);
@@ -568,6 +598,52 @@ async function parseTranscriptIncremental(transcriptPath, lastSavedLine) {
568
598
 
569
599
  // lib/save/index.ts
570
600
  var { DatabaseSync: DatabaseSync3 } = await import("node:sqlite");
601
+ function normalizeFilePath(absPath, projectPath) {
602
+ if (!absPath.startsWith(projectPath)) return null;
603
+ return absPath.slice(projectPath.length).replace(/^\//, "");
604
+ }
605
+ var IGNORED_PREFIXES = [
606
+ "node_modules/",
607
+ "dist/",
608
+ ".git/",
609
+ ".mneme/",
610
+ ".claude/"
611
+ ];
612
+ var IGNORED_FILES = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock"];
613
+ function isIgnoredPath(relativePath) {
614
+ return IGNORED_PREFIXES.some((p) => relativePath.startsWith(p)) || IGNORED_FILES.includes(relativePath);
615
+ }
616
+ function indexFilePaths(fileIndexStmt, interaction, mnemeSessionId, projectPath) {
617
+ const seen = /* @__PURE__ */ new Set();
618
+ const add = (absPath, toolName) => {
619
+ const normalized = normalizeFilePath(absPath, projectPath);
620
+ if (!normalized || isIgnoredPath(normalized) || seen.has(normalized))
621
+ return;
622
+ seen.add(normalized);
623
+ try {
624
+ fileIndexStmt.run(
625
+ mnemeSessionId,
626
+ projectPath,
627
+ normalized,
628
+ toolName,
629
+ interaction.timestamp
630
+ );
631
+ } catch {
632
+ }
633
+ };
634
+ for (const td of interaction.toolDetails) {
635
+ if (typeof td.detail === "string" && td.detail.startsWith("/")) {
636
+ add(td.detail, td.name);
637
+ }
638
+ }
639
+ if (interaction.toolResults) {
640
+ for (const tr of interaction.toolResults) {
641
+ if (tr.filePath?.startsWith("/")) {
642
+ add(tr.filePath, tr.toolName || "");
643
+ }
644
+ }
645
+ }
646
+ }
571
647
  async function incrementalSave(claudeSessionId, transcriptPath, projectPath) {
572
648
  if (!claudeSessionId || !transcriptPath || !projectPath) {
573
649
  return {
@@ -613,6 +689,10 @@ async function incrementalSave(claudeSessionId, transcriptPath, projectPath) {
613
689
  owner, role, content, thinking, tool_calls, timestamp, is_compact_summary
614
690
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
615
691
  `);
692
+ const fileIndexStmt = db.prepare(`
693
+ INSERT INTO file_index (session_id, project_path, file_path, tool_name, timestamp)
694
+ VALUES (?, ?, ?, ?, ?)
695
+ `);
616
696
  let insertedCount = 0;
617
697
  let lastTimestamp = saveState.lastSavedTimestamp || "";
618
698
  for (const interaction of interactions) {
@@ -676,6 +756,7 @@ async function incrementalSave(claudeSessionId, transcriptPath, projectPath) {
676
756
  );
677
757
  insertedCount++;
678
758
  }
759
+ indexFilePaths(fileIndexStmt, interaction, mnemeSessionId, projectPath);
679
760
  lastTimestamp = interaction.timestamp;
680
761
  } catch (error) {
681
762
  console.error(`[mneme] Error inserting interaction: ${error}`);