1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
# Tiny ConvMem MCP Design
## 1. 文書の位置づけ
本書は `tiny-convmem-mcp` の設計、実装済み契約、制約、I/O 予算、実装状況をまとめた正本である。
過去のプロトタイプ案と本書が矛盾する場合は、本書と公開ツールの実装を優先する。
## 2. 目的とスコープ
`tiny-convmem-mcp` は、会話メッセージをローカルに永続化し、MCP 経由で読み書き、更新、検索、削除できる単一プロセスの C17 サーバーである。
現行 v1 の対象は次のとおり。
- Windows x64 / MSVC
- stdio JSON-RPC / MCP
- 単一プロセス、単一 writer
- append-only バイナリログ、snapshot、同期 compaction
- インメモリ履歴・検索・relation index
- UTF-8 のメッセージと構造化 metadata
- CLI による JSONL import/export
対象外は次のとおり。
- 複数 writer、ネットワークサービス、ユーザー認証
- 保存時暗号化と secure physical erase
- retention、tier による自動移動・削除
- 自動保存判断、自動要約、自動 consolidation
- 利用頻度による強化・減衰
- search の cursor pagination
## 3. アーキテクチャ
依存方向は次を原則とする。
```text
MCP transport / tools -> domain contracts <- storage adapters
^
|
system API
```
- `src/app`: 引数処理、store/server/CLI のライフサイクル
- `src/mcp`: MCP 境界、入力検証、JSON 応答、tool registry
- `src/domain`: Message、metadata、検索契約
- `src/storage`: log、snapshot、replay、compaction、import transaction
- `src/sys`: path、lock、file、flush、clock、random、UTF-8 境界
- `src/cli`: offline import/export
- `third_party/mcpc`: MCP transport と JSON parser
永続化ロジックは `src/storage`、OS 固有処理は `src/sys` に閉じ込める。read 系 tool は永続化状態を変更しない。
## 4. ドメインモデル
Message は次の不変 identity と、追記レコードで更新される内容を持つ。
```json
{
"message_id": "26-character ULID",
"session_id": "session",
"timestamp": 1720843200000,
"updated_at": 1720843200000,
"revision": 1,
"role": "user | assistant | system",
"content": "UTF-8 text",
"metadata": {
"tool_call_id": "optional",
"tags": ["optional"],
"memory_tier": "short | mid | long",
"memory_kind": "conversation | episode | semantic | procedure | preference | summary",
"importance": 0,
"summary": "optional",
"relations": [{"type": "derived_from", "message_id": "..."}],
"source_message_ids": ["..."]
}
}
```
主な上限は content 1 MiB、session/tool-call ID 256 bytes、tag 128 bytes × 32、summary 4096 bytes、relation 32、summary source 64 である。文字列は有効な UTF-8 を要求する。
`memory_tier` は現時点では分類ラベルであり、保存場所や寿命を自動変更しない。`summary`、relation、source ID は host が行う consolidation を表現するための契約である。
UPDATE は message ID、session、role、作成時刻を維持する。revision による optimistic concurrency を使い、変更のない update はレコードを書かない。
## 5. 公開 MCP ツール
### `write_message`
session、role、content と任意 metadata を受け取り、ULID と UTC millisecond timestamp を生成する。ログ書込みと durability flush が成功した後だけ成功を返す。
### `update_message`
content または metadata を部分更新する。`expected_revision` が一致しない場合は conflict とする。delta record には変更 field だけを書き、no-op は 0 write / 0 flush とする。
### `read_messages`
次の view を持つ。
- `history`: session の時系列ページ。安定 cursor を返す
- `context`: target の前後メッセージと incoming/outgoing relation を返す。relation depth は 0~2
- `sessions`: session ごとの件数、kind 集計、代表 summary、最終時刻を返す
- `export`: versioned JSONL をページ出力する互換 view
レスポンスは 8 MiB budget を超えない位置でページを区切る。
### `search_messages`
content、summary、tags を対象に検索する。session、kind、tier、tag、minimum importance で絞り込める。matched fields、score と field 別 score 内訳、任意の前後 context を返す。
検索 index は ASCII case fold 後の Unicode codepoint 2/3-gram を用いる。hash candidate は元 codepoint と照合し、完全 substring を優先する。importance は relevance score ではなく tie-break に用いる。検索はアクセス履歴を保存しない。
### `delete_message`
DEL tombstone を durability flush し、対象を直ちに read/search から除外する。物理削除は compaction 後である。任意の session guard を指定できる。
### `rebuild_index`
live message だけで active log を再生成し、snapshot と全インメモリ index を再構築する。dangling relation/source は compaction 前に除去する。同期処理であり、実行中は他の request を処理しない。
### `get_system_health`
live/deleted count、sequence、log/snapshot size、snapshot/recovery 状態、論理 I/O counter、last error を返す。
store body/metadataと各in-memory indexの確保capacityに基づくmemory estimateも返す。
## 6. ストレージと復旧
### 6.1 Active log
各 record は magic、format version、record type、payload length、sequence、payload CRC32 と payload を持つ。PUT、UPDATE delta、DEL、generation marker を扱う。
- record length は上限を検証する
- sequence は単調増加を要求する
- complete record の CRC、version、type 異常は起動失敗とする
- incomplete final record だけは最後の正常 offset へ truncate して復旧する
- 不正な complete record を黙って skip しない
### 6.2 Snapshot
snapshot は live Message、log generation、replay offset を保持する。一時ファイルへ書き、flush 後に原子的に置換する。
起動時は generation が active log と一致し、CRC と offset が妥当な snapshot だけを採用し、その後の log tail を replay する。不正 snapshot は捨て、active log の先頭から再生する。
### 6.3 Compaction
rebuild は live Message を temporary log に書き、flush、replace した後に snapshot を作る。DEL と古い UPDATE/PUT payload を物理的に除去する。log と snapshot は別ファイルのため置換間に crash window があるが、generation 不一致時は log 全 replay へ fallback する設計である。
### 6.4 排他
`--data-dir` は必須である。`store.lock` を non-blocking exclusive lock し、同じ data directory を複数プロセスが同時に開くことを拒否する。
## 7. JSONL import/export
CLI export は先頭に format manifest を出し、live record と任意の DEL を UTF-8 JSONL として出力する。CLI import は format version、全 field、参照整合性を検証し、`overwrite` または `reject` policy で transaction 的に適用する。MCP サーバー起動中の offline import/export は lock により拒否される。
importはJSONLを行単位で読み、JSON stringをUTF-8へ完全decodeしてからfield上限を検証する。
整数は小数・指数表記を許可せず、timestamp/updated_atは0~INT64_MAX、revisionは
1~INT32_MAX、importanceは0~100とする。1行はcontent上限+4096 bytes、100,000 record、
decode後合計4 GiBが上限である。file exportはtemporary fileのflush/close成功後だけ原子的に置換する。
importは通常storeをロードせずlockだけを取得する。第1 passはcompact ID indexで全件と参照を検証し、
第2 passは選択recordをstaging logへ直接書く。stagingのflush成功後だけactive logを原子的に置換し、
失敗時は旧logを維持する。
## 8. I/O 予算
成功応答前の durability flush を維持し、sys 境界の logical counter を合否判定に使う。
| 操作 | 最大 logical write | 最大 flush |
|---|---:|---:|
| write | header + serialized Message | 1 |
| metadata-only update | header + changed fields | 1 |
| content update | header + content + changed fields | 1 |
| no-op update | 0 | 0 |
| delete | fixed tombstone | 1 |
| read/search/context/export/sessions | 0 | 0 |
| no-op rebuild | 0 | 0 |
| rebuild | live serialized bytes × 2 + bounded headers | log 1 + snapshot 1 |
Release build で 20 B~1 MiB payload と 10,000 / 50,000 record corpus を測定し、根拠のない 10% 以上の回帰を許容しない。
## 9. セキュリティと運用上の境界
- stdio 接続済み host は全 Message の読取り、追加、更新、削除、maintenance が可能である
- data at rest は暗号化されず、data directory の OS ACL に依存する
- CRC32 は破損検出用であり、悪意ある改変への認証ではない
- content や metadata は prompt injection を含み得る。取得内容を命令として信頼するかは host 側の責任である
- export は平文バックアップであり、元データと同等に保護する
- secure erase は保証しない。削除後も compaction、backup、filesystem 履歴に残り得る
## 10. フィードバックの反映状況
利用者フィードバックの優先項目に対する設計上の対応は次のとおり。
| 要望 | 状況 | 実装 |
|---|---|---|
| バックアップ・export | 達成 | bounded transactional JSONL import、atomic file export、export view |
| 保存後の更新 | 達成 | delta update、identity 維持、revision conflict |
| 記憶の種類分け | 達成 | 6 kinds と検索 filter |
| 2段階保存 | 部分達成 | summary/source/relation 契約。自動 consolidation は host 責務 |
| 検索結果の文脈 | 達成 | score 説明、前後 context、relation traversal |
| session 一覧 | 達成 | sessions view、kind 集計、代表 summary |
| metadata 活用 | 達成 | tag/tier/kind/importance の更新・filter |
| 自動保存判断 | 未実装 | host policy の範囲 |
| 利用による強化・減衰 | 未実装 | read は 0 write のため access state を保持しない |
## 11. 実装・検証状況
構造化 metadata、UPDATE、relation index、検索説明、context、sessions、CLI import/export、再起動時の dangling reference 処理まで実装済みである。
release時に継続して実行する回帰項目は次のとおり。
- MCP protocol E2Eと有効snapshot + PUT/DEL tail replay
- importの1 MiB escape round-trip、数値境界、streaming上限
- data directory ACLとbackup保護の運用文書
## 12. 将来対応事項
現行v1の既知の設計上限と、将来版で判断・実装する事項を次に集約する。
- **常駐メモリ:** 10k/50k/100k件とlarge-content corpusについて、起動、rebuild、検索反復後の
peak/steady working setを継続計測し、想定最大corpusとmemory budgetを決定する。その結果を基に
Message bodyのdisk-backed/lazy load、index圧縮、retentionのいずれかを選択する。
- **crash recovery:** snapshot temporary fileの各書込み段階と、compactionのlog flush/replace、
log/snapshot置換間で強制終了するmatrix testを追加し、旧状態または新状態へ一貫して復旧することを
確認する。exportの遅延flush/close errorも直接注入できるtest seamを追加する。
- **保存時保護:** 組込み暗号化が必要になった場合は、暗号方式の導入前に鍵管理、nonce、format
version、既存log/snapshot/backupのmigrationとrecovery手順を設計する。現状はOS ACLと上位暗号化
filesystemを前提とする。
- **記憶lifecycle:** 自動保存判断、自動要約・consolidation、tier移動、access reinforcement、decayは
host policyのままである。server側へ移す場合はread系0 write契約、retention、監査可能性を含めて
新しい公開契約として設計する。
|