@hir4ta/memoria 0.3.2 → 0.3.3
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/plugin.json +1 -1
- package/README.md +3 -3
- package/dist/public/assets/{index-_hbs7Kn1.js → index-BpBWarmo.js} +6 -6
- package/dist/public/index.html +1 -1
- package/hooks/session-end.sh +101 -0
- package/hooks/session-start.sh +24 -0
- package/package.json +1 -1
- package/skills/decision/skill.md +49 -2
- package/skills/using-memoria/skill.md +32 -3
package/dist/public/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>memoria - Dashboard</title>
|
|
7
7
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BpBWarmo.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-CC2t4_6M.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/hooks/session-end.sh
CHANGED
|
@@ -179,4 +179,105 @@ echo "$session_json" > "$session_path"
|
|
|
179
179
|
# Log to stderr (not shown to user but helpful for debugging)
|
|
180
180
|
echo "[memoria] Session saved to ${session_path}" >&2
|
|
181
181
|
|
|
182
|
+
# ============================================
|
|
183
|
+
# Auto-detect design decisions from conversation
|
|
184
|
+
# ============================================
|
|
185
|
+
|
|
186
|
+
decisions_dir="${memoria_dir}/decisions"
|
|
187
|
+
mkdir -p "$decisions_dir"
|
|
188
|
+
|
|
189
|
+
# Extract potential decisions from assistant messages
|
|
190
|
+
# Look for patterns indicating design decisions
|
|
191
|
+
detected_decisions=$(echo "$messages" | jq -r '
|
|
192
|
+
# Get all assistant messages with thinking or content
|
|
193
|
+
[.[] | select(.type == "assistant")] |
|
|
194
|
+
|
|
195
|
+
# Combine thinking and content for analysis
|
|
196
|
+
map({
|
|
197
|
+
thinking: (.thinking // ""),
|
|
198
|
+
content: (.content // ""),
|
|
199
|
+
timestamp: .timestamp
|
|
200
|
+
}) |
|
|
201
|
+
|
|
202
|
+
# Filter messages that contain decision-related keywords
|
|
203
|
+
map(select(
|
|
204
|
+
(.thinking + " " + .content) | test(
|
|
205
|
+
"決定|採用|選択|することにした|ことにする|方針|architecture|decision|approach|strategy|instead of|rather than|選んだ|使うことに|実装方針|設計判断";
|
|
206
|
+
"i"
|
|
207
|
+
)
|
|
208
|
+
)) |
|
|
209
|
+
|
|
210
|
+
# Extract decision-like sentences
|
|
211
|
+
map({
|
|
212
|
+
timestamp: .timestamp,
|
|
213
|
+
text: ((.thinking // "") + "\n" + (.content // ""))
|
|
214
|
+
})
|
|
215
|
+
')
|
|
216
|
+
|
|
217
|
+
decision_count=$(echo "$detected_decisions" | jq 'length')
|
|
218
|
+
|
|
219
|
+
if [ "$decision_count" -gt 0 ]; then
|
|
220
|
+
# Process each detected decision
|
|
221
|
+
decision_index=0
|
|
222
|
+
echo "$detected_decisions" | jq -c '.[]' | while read -r decision_data; do
|
|
223
|
+
decision_index=$((decision_index + 1))
|
|
224
|
+
|
|
225
|
+
timestamp=$(echo "$decision_data" | jq -r '.timestamp')
|
|
226
|
+
text=$(echo "$decision_data" | jq -r '.text')
|
|
227
|
+
|
|
228
|
+
# Generate decision ID
|
|
229
|
+
decision_id="${date_part}-auto-${session_short_id}-$(printf "%03d" $decision_index)"
|
|
230
|
+
|
|
231
|
+
# Extract a title from the text (first significant sentence)
|
|
232
|
+
title=$(echo "$text" | head -c 500 | grep -oE '(決定|採用|選択|方針|実装)[^。.\n]{5,50}' | head -1 || echo "Auto-detected decision")
|
|
233
|
+
if [ -z "$title" ] || [ "$title" = "Auto-detected decision" ]; then
|
|
234
|
+
title=$(echo "$text" | head -c 100 | tr '\n' ' ' | sed 's/^[[:space:]]*//' | cut -c1-50)
|
|
235
|
+
[ -n "$title" ] && title="${title}..."
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
# Extract key decision content (sentences with decision keywords)
|
|
239
|
+
decision_content=$(echo "$text" | grep -oE '[^。.\n]*?(決定|採用|選択|することにした|ことにする|方針)[^。.\n]*[。.]?' | head -3 | tr '\n' ' ' || echo "$text" | head -c 200)
|
|
240
|
+
|
|
241
|
+
# Build decision JSON
|
|
242
|
+
decision_json=$(jq -n \
|
|
243
|
+
--arg id "$decision_id" \
|
|
244
|
+
--arg title "$title" \
|
|
245
|
+
--arg decision "$decision_content" \
|
|
246
|
+
--arg createdAt "$timestamp" \
|
|
247
|
+
--arg userName "$git_user_name" \
|
|
248
|
+
--arg userEmail "$git_user_email" \
|
|
249
|
+
--arg branch "$current_branch" \
|
|
250
|
+
--arg projectDir "$cwd" \
|
|
251
|
+
--arg sessionId "$file_id" \
|
|
252
|
+
--arg source "auto" \
|
|
253
|
+
'{
|
|
254
|
+
id: $id,
|
|
255
|
+
title: $title,
|
|
256
|
+
decision: $decision,
|
|
257
|
+
reasoning: "Auto-detected from session conversation",
|
|
258
|
+
alternatives: [],
|
|
259
|
+
tags: ["auto-detected"],
|
|
260
|
+
createdAt: $createdAt,
|
|
261
|
+
user: {
|
|
262
|
+
name: $userName,
|
|
263
|
+
email: (if $userEmail == "" then null else $userEmail end)
|
|
264
|
+
} | with_entries(select(.value != null)),
|
|
265
|
+
context: {
|
|
266
|
+
branch: (if $branch == "" then null else $branch end),
|
|
267
|
+
projectDir: $projectDir
|
|
268
|
+
} | with_entries(select(.value != null)),
|
|
269
|
+
relatedSessions: [$sessionId],
|
|
270
|
+
source: $source,
|
|
271
|
+
status: "draft"
|
|
272
|
+
}')
|
|
273
|
+
|
|
274
|
+
# Save decision (only if not duplicate)
|
|
275
|
+
decision_path="${decisions_dir}/${decision_id}.json"
|
|
276
|
+
if [ ! -f "$decision_path" ]; then
|
|
277
|
+
echo "$decision_json" > "$decision_path"
|
|
278
|
+
echo "[memoria] Decision auto-detected: ${decision_path}" >&2
|
|
279
|
+
fi
|
|
280
|
+
done
|
|
281
|
+
fi
|
|
282
|
+
|
|
182
283
|
exit 0
|
package/hooks/session-start.sh
CHANGED
|
@@ -53,12 +53,36 @@ if [ -d "$sessions_dir" ]; then
|
|
|
53
53
|
fi
|
|
54
54
|
fi
|
|
55
55
|
|
|
56
|
+
# Find draft decisions (auto-detected but not reviewed)
|
|
57
|
+
decisions_dir="${memoria_dir}/decisions"
|
|
58
|
+
draft_decisions=""
|
|
59
|
+
if [ -d "$decisions_dir" ] && command -v jq &> /dev/null; then
|
|
60
|
+
decision_files=$(find "$decisions_dir" -name "*.json" -type f 2>/dev/null)
|
|
61
|
+
|
|
62
|
+
for file in $decision_files; do
|
|
63
|
+
if [ -f "$file" ]; then
|
|
64
|
+
# Check if it's a draft (auto-detected)
|
|
65
|
+
is_draft=$(jq -r 'select(.status == "draft") | .id' "$file" 2>/dev/null || echo "")
|
|
66
|
+
if [ -n "$is_draft" ]; then
|
|
67
|
+
decision_info=$(jq -r '"\(.id): \(.title // "no title")"' "$file" 2>/dev/null || echo "")
|
|
68
|
+
if [ -n "$decision_info" ]; then
|
|
69
|
+
draft_decisions="${draft_decisions} - ${decision_info}\n"
|
|
70
|
+
fi
|
|
71
|
+
fi
|
|
72
|
+
fi
|
|
73
|
+
done
|
|
74
|
+
fi
|
|
75
|
+
|
|
56
76
|
# Build context message
|
|
57
77
|
context_parts=""
|
|
58
78
|
if [ -n "$related_sessions" ]; then
|
|
59
79
|
context_parts="[memoria] 関連セッションが見つかりました:\n\n${related_sessions}\n\`/memoria:resume <id>\` で過去のセッションを再開できます。"
|
|
60
80
|
fi
|
|
61
81
|
|
|
82
|
+
if [ -n "$draft_decisions" ]; then
|
|
83
|
+
context_parts="${context_parts}\n\n[memoria] 未レビューの設計決定(自動検出):\n\n${draft_decisions}\nダッシュボードで確認・編集できます: \`npx @hir4ta/memoria --dashboard\`"
|
|
84
|
+
fi
|
|
85
|
+
|
|
62
86
|
# Escape for JSON
|
|
63
87
|
escape_for_json() {
|
|
64
88
|
local input="$1"
|
package/package.json
CHANGED
package/skills/decision/skill.md
CHANGED
|
@@ -7,6 +7,18 @@ description: 設計決定を記録する。
|
|
|
7
7
|
|
|
8
8
|
設計決定(ADR: Architecture Decision Record)を記録するスキルです。
|
|
9
9
|
|
|
10
|
+
## 自動保存 vs 手動保存
|
|
11
|
+
|
|
12
|
+
| 保存方式 | タイミング | ステータス |
|
|
13
|
+
|---------|-----------|-----------|
|
|
14
|
+
| **自動** | セッション終了時 | `draft`(要レビュー) |
|
|
15
|
+
| **手動** | `/memoria:decision` 実行時 | `active`(確定) |
|
|
16
|
+
|
|
17
|
+
- **自動保存**: セッション終了時に会話から設計決定を自動検出・保存(`status: draft`)
|
|
18
|
+
- **手動保存**: このコマンドで明示的に記録(`status: active`)
|
|
19
|
+
|
|
20
|
+
自動検出された決定はダッシュボードでレビュー・編集できます。
|
|
21
|
+
|
|
10
22
|
## 使い方
|
|
11
23
|
|
|
12
24
|
```
|
|
@@ -18,7 +30,7 @@ description: 設計決定を記録する。
|
|
|
18
30
|
## 実行手順
|
|
19
31
|
|
|
20
32
|
1. タイトルを受け取る(引数から、または対話で入力)
|
|
21
|
-
2.
|
|
33
|
+
2. 以下の情報を会話コンテキストから抽出(または対話で収集):
|
|
22
34
|
- decision: 何を決定したか
|
|
23
35
|
- reasoning: なぜその決定をしたか
|
|
24
36
|
- alternatives: 検討した代替案(オプション)
|
|
@@ -57,10 +69,29 @@ Write: .memoria/decisions/jwt-auth-001.json
|
|
|
57
69
|
"context": {
|
|
58
70
|
"branch": "feature/auth",
|
|
59
71
|
"projectDir": "/path/to/project"
|
|
60
|
-
}
|
|
72
|
+
},
|
|
73
|
+
"relatedSessions": ["2026-01-24_abc123"],
|
|
74
|
+
"source": "manual",
|
|
75
|
+
"status": "active"
|
|
61
76
|
}
|
|
62
77
|
```
|
|
63
78
|
|
|
79
|
+
### status フィールド
|
|
80
|
+
|
|
81
|
+
| 値 | 説明 |
|
|
82
|
+
|---|------|
|
|
83
|
+
| `draft` | 自動検出(要レビュー) |
|
|
84
|
+
| `active` | 確定済み |
|
|
85
|
+
| `superseded` | 後の決定で置き換え |
|
|
86
|
+
| `deprecated` | 非推奨 |
|
|
87
|
+
|
|
88
|
+
### source フィールド
|
|
89
|
+
|
|
90
|
+
| 値 | 説明 |
|
|
91
|
+
|---|------|
|
|
92
|
+
| `auto` | セッション終了時に自動検出 |
|
|
93
|
+
| `manual` | `/memoria:decision` で手動記録 |
|
|
94
|
+
|
|
64
95
|
## ID生成ルール
|
|
65
96
|
|
|
66
97
|
タイトルからスラッグを生成:
|
|
@@ -92,6 +123,22 @@ Write: .memoria/decisions/jwt-auth-001.json
|
|
|
92
123
|
> auth, architecture, jwt
|
|
93
124
|
```
|
|
94
125
|
|
|
126
|
+
### 会話コンテキストからの自動抽出
|
|
127
|
+
|
|
128
|
+
現在の会話で設計決定がすでに議論されている場合、Claudeがコンテキストから自動的に抽出して記録します。
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
> /memoria:decision "認証方式の選択"
|
|
132
|
+
|
|
133
|
+
会話コンテキストから以下の情報を抽出しました:
|
|
134
|
+
|
|
135
|
+
- 決定: セッション管理にJWTを採用する
|
|
136
|
+
- 理由: マイクロサービス間での認証共有が容易
|
|
137
|
+
- 代替案: セッションCookie(却下理由: スケールしにくい)
|
|
138
|
+
|
|
139
|
+
この内容で保存しますか?(修正する場合は内容を入力)
|
|
140
|
+
```
|
|
141
|
+
|
|
95
142
|
## 出力フォーマット
|
|
96
143
|
|
|
97
144
|
```
|
|
@@ -11,18 +11,29 @@ memoriaはClaude Codeに長期記憶を与えるプラグインです。
|
|
|
11
11
|
|
|
12
12
|
1. **セッション自動保存**: セッション終了時・コンパクト時に会話履歴を自動保存
|
|
13
13
|
2. **セッション再開**: `/memoria:resume` で過去のセッションを復元
|
|
14
|
-
3. **設計決定記録**: `/memoria:decision`
|
|
14
|
+
3. **設計決定記録**: セッション終了時に自動検出 + `/memoria:decision` で手動記録
|
|
15
15
|
4. **ナレッジ検索**: `/memoria:search` で保存した情報を検索
|
|
16
16
|
5. **Webダッシュボード**: セッション・決定・パターンを視覚的に管理
|
|
17
17
|
|
|
18
|
+
## 設計決定の自動保存
|
|
19
|
+
|
|
20
|
+
| 保存方式 | タイミング | ステータス |
|
|
21
|
+
|---------|-----------|-----------|
|
|
22
|
+
| **自動** | セッション終了時 | `draft`(要レビュー) |
|
|
23
|
+
| **手動** | `/memoria:decision` 実行時 | `active`(確定) |
|
|
24
|
+
|
|
25
|
+
セッション終了時に、会話から設計決定を自動検出して保存します(`status: draft`)。
|
|
26
|
+
自動検出された決定はダッシュボードでレビュー・編集できます。
|
|
27
|
+
|
|
18
28
|
## コマンド
|
|
19
29
|
|
|
20
30
|
| コマンド | 説明 |
|
|
21
31
|
|---------|------|
|
|
22
32
|
| `/memoria:resume [id]` | セッションを再開(ID省略で一覧) |
|
|
23
33
|
| `/memoria:save` | 現在のセッションを手動保存 |
|
|
24
|
-
| `/memoria:decision "タイトル"` |
|
|
34
|
+
| `/memoria:decision "タイトル"` | 設計決定を記録(確定) |
|
|
25
35
|
| `/memoria:search <query>` | ナレッジを検索 |
|
|
36
|
+
| `/memoria:dashboard` | ダッシュボードURL表示 |
|
|
26
37
|
|
|
27
38
|
## ダッシュボード
|
|
28
39
|
|
|
@@ -86,6 +97,24 @@ npx @hir4ta/memoria --dashboard
|
|
|
86
97
|
"alternatives": ["Session Cookie", "OAuth2"],
|
|
87
98
|
"tags": ["auth", "architecture"],
|
|
88
99
|
"createdAt": "2026-01-24T10:00:00Z",
|
|
89
|
-
"user": { "name": "user" }
|
|
100
|
+
"user": { "name": "user" },
|
|
101
|
+
"source": "manual",
|
|
102
|
+
"status": "active"
|
|
90
103
|
}
|
|
91
104
|
```
|
|
105
|
+
|
|
106
|
+
### status フィールド
|
|
107
|
+
|
|
108
|
+
| 値 | 説明 |
|
|
109
|
+
|---|------|
|
|
110
|
+
| `draft` | 自動検出(要レビュー) |
|
|
111
|
+
| `active` | 確定済み |
|
|
112
|
+
| `superseded` | 後の決定で置き換え |
|
|
113
|
+
| `deprecated` | 非推奨 |
|
|
114
|
+
|
|
115
|
+
### source フィールド
|
|
116
|
+
|
|
117
|
+
| 値 | 説明 |
|
|
118
|
+
|---|------|
|
|
119
|
+
| `auto` | セッション終了時に自動検出 |
|
|
120
|
+
| `manual` | `/memoria:decision` で手動記録 |
|