summaryrefslogtreecommitdiff
path: root/docs/Design.md
diff options
context:
space:
mode:
authortanaka takashi <isazaka@gmail.com>2026-07-04 18:44:17 +0900
committertanaka takashi <isazaka@gmail.com>2026-07-04 18:44:17 +0900
commit751999a82b8854ef5231e0ded5fe022b1ea5d8ff (patch)
treed09653d2955f0f5354e9ef76f9bc550fb8f0732a /docs/Design.md
parent21dda921887da2515d1eba0d3d26e2036bf9f7f7 (diff)
Harden backup import and restore coverage
Diffstat (limited to 'docs/Design.md')
-rw-r--r--docs/Design.md216
1 files changed, 216 insertions, 0 deletions
diff --git a/docs/Design.md b/docs/Design.md
new file mode 100644
index 0000000..3485a73
--- /dev/null
+++ b/docs/Design.md
@@ -0,0 +1,216 @@
+# Tiny ConvMem MCP Design
+
+## 1. 文書の位置づけ
+
+本書は `tiny-convmem-mcp` の設計、実装済み契約、制約、I/O 予算、実装状況をまとめた正本である。
+過去のプロトタイプ案と本書が矛盾する場合は、本書と公開ツールの実装を優先する。
+
+診断結果と次タスクは [Review.md](Review.md) を参照する。
+
+## 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成功後だけ原子的に置換する。
+
+## 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 | 部分達成 | JSONL CLI と export view。import 完全性に既知課題あり |
+| 保存後の更新 | 達成 | 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 処理まで実装済みである。
+
+継続的に再検証する項目は次のとおり。
+
+- MCP protocol E2Eと有効snapshot + PUT/DEL tail replay
+- snapshot temporary file 各段階の強制終了試験
+- compaction の flush/replace 前後と log/snapshot 間 crash matrix
+- importの1 MiB escape round-trip、数値境界、streaming上限
+- live corpus増加時のmemory benchmark(retentionはv1対象外)
+- data directory ACLとbackup保護の運用文書
+
+具体的な優先順位と完了条件は [Review.md](Review.md) に記載する。