メモリシステムの設計

This commit is contained in:
2026-04-21 19:23:07 +09:00
parent 47da4a03cb
commit ca5a3d1152
4 changed files with 178 additions and 35 deletions
+72 -28
View File
@@ -6,39 +6,66 @@ INSOMNIA がユーザーのプロジェクトに対して提供するメモリ
リサーチは `docs/ref/memory-systems.md`。前提として、**レポジトリがファイルシステム上にある**ケースで設計する(越境・バックエンド抽象は Scope 外)。
Workflow`/workflow-name` で呼び出される制約付き作業フロー)は別 plan に切り出した。`docs/plan/workflow.md` 参照。
Workflow`/<slug>` で呼び出される制約付き作業フロー)は別 plan に切り出した。`docs/plan/workflow.md` 参照。
## 決定事項
### 記録対象の 5 種
| 種別 | パス | 備考 |
| ---------------- | ---------------------------- | -------------------------------------------------------------------------------------------- |
| Always-on サマリ | `memory/summary.md` | 1-5k tokens 目安 |
| Lessons | `memory/lessons/<id>.md` | |
| Decisions | `memory/decisions/<id>.md` | `status: open \| resolved \| superseded` で未決議論も保持、supersede は `superseded_by` 参照 |
| Requests | `memory/requests/<id>.md` | ユーザー submit の構造化要約 |
| Knowledge | `memory/knowledge/<name>.md` | `#name` で注入。ノウハウ / 用語 / 運用方針 / ルール / 事実など型を設けず Markdown 自由記述 |
| 種別 | パス | 備考 |
| ---------------- | ------------------------------ | ----------------------------------------------------------------------------------------------- |
| Always-on サマリ | `memory/summary.md` | 1-5k tokens 目安 |
| Lessons | `memory/lessons/<slug>.md` | |
| Decisions | `memory/decisions/<slug>.md` | `status: open \| resolved \| replaced` で未決議論も保持、置き換え時は `replaced_by: <slug>` |
| Requests | `memory/requests/<slug>.md` | ユーザー submit の構造化要約 |
| Knowledge | `memory/knowledge/<slug>.md` | `#slug` で注入。ノウハウ / 用語 / 運用方針 / ルール / 事実など型を設けず Markdown 自由記述 |
- `<id>`UUIDv7(時系列順に並ぶ)、`<name>` は slug(小文字英数とハイフン)
- `<slug>`kebab-case(内容を要約した短い識別子)。**ファイル名そのものが ID**、frontmatter に別途 `id` field は持たない
- **1 件 1 ファイル**。append-only な複数エントリログファイルは作らない
- Phase 1 の中間ストアとして `memory/_staging/<id>.json` を使う(Phase 2 完了で cleanup、後述
- **同一 slug の衝突は新規作成禁止**。既存があれば updateLinter で検証、sub-Worker は read→edit に切り替え
- 同主題の content 進化 = 上書き update + git log で履歴追跡
- 別主題が古い主題を置き換える場合のみ、別 slug で新規作成し古い方に `status: replaced` + `replaced_by: <新 slug>` を記録
- Phase 1 の中間ストアとして `memory/_staging/<id>.json` を使う(短命、P2 完了で cleanup。ここは衝突回避と順序のため UUIDv7 可)
- Raw session log は既存 `llm-worker-persistence` で保持する。memory 対象外、参照経路のみ
### Knowledge の呼び出し制御
agentskills.io の `SKILL.md` 形式は採用しない。Knowledge は `#knowledge-name` でユーザー / LLM から注入参照する。名前空間は**フラット**、name は slug
agentskills.io の `SKILL.md` 形式は採用しない。Knowledge は `#<slug>` でユーザー / LLM から注入参照する。名前空間は**フラット**、slug は kebab-case(小文字英数とハイフン)
| フラグ | 意味 | デフォルト |
| ---------------- | ------------------------------------------------------- | ---------- |
| `auto_invoke` | description が LLM context に載り、LLM が自発的に呼べる | **OFF** |
| `user_invocable` | ユーザーが `#` で明示的に呼べる | **ON** |
| `user_invocable` | ユーザーが `#<slug>` で明示的に呼べる | **ON** |
`auto_invoke` の ON 化は人間の判断、または consolidation が頻繁に `user_invoke` されているものを検出して offer する。自律的に新規エンティティを生成はしない。Workflow も同じフラグ仕様(`workflow.md` 参照)。
### 書き込み先の制約
### 書き込み経路と Linter
`memory/workflow/` への自動書き込みは、consolidation Worker の structured output schema に `workflow` カテゴリを含めないことで担保する(後述、および `workflow.md`)。OS ファイル権限や Scope 上の特別な保護機構は設けず、`memory/` 配下を write allow する以上の細工はしない。衝突は git で解決する前提
人間も consolidation sub-Worker も**同じ CRUD toolfile read / write / edit**で `memory/*` を触る。書き込み時の制約は Linter で検証し、違反時は post-write Hook が turn を戻して sub-Worker に自己修正させる(N 回失敗で abort)
Linter ルールは 2 系統:
**静的 error**post-write Hook で turn 戻し、sub-Worker が自己修正):
- frontmatter 必須 field
- Lessons / Decisions / Requests: `created_at`, `updated_at`, `sources`
- Knowledge: `description`, `auto_invoke`, `user_invocable`, `last_sources`, `created_at`, `updated_at`
- Summary: `updated_at`optional: `last_rewritten_from_range`
- `memory/workflow/` への書き込み禁止(sub-Worker context のみ、人間編集は除外)
- 同 slug での新規作成禁止(既存があれば update に切り替えるサイン)
- `#<slug>` 参照が実在ファイルを指す
- `replaced_by: <slug>` が実在 record を指す
- Decisions の `status` は enum `open | resolved | replaced`
- `auto_invoke: true` の record は description 文字数上限(agentskills 準拠 1024 chars
- 種別ごとの char 硬上限(具体値は運用で調整、設定ファイルで tune)
**膨張抑制 Warn**(error ではなく改善ヒント、sub-Worker は task 余力があれば対応):
- 重要度 × char の天秤: 低重要度で char 使用過多な record に「圧縮余地あり」Warn
- sources 累積: 配列が閾値超過で「直近 N 件に絞り過去は git log に委ねる候補」Warn
- 類似 slug 乱立: 近似 slug の集合に「merge 候補」Warn
Workflow 保護は専用 tool schema のトリックではなく Linter ルールで担保するため、人間が規則を読んで理解できる。OS ファイル権限や Scope 上の特別な保護機構は設けず、`memory/` 配下を write allow する以上の細工はしない。衝突は git で解決する前提。
### 自動化(consolidation)メカニズム
@@ -56,6 +83,7 @@ agentskills.io の `SKILL.md` 形式は採用しない。Knowledge は `#knowled
- `requests`: ユーザー submit の構造化要約(意図 / 対象 / 要約)
- **抽出対象がなければ空配列を返してよい**(Hermes の "Nothing to save." と同系。頻繁発火を許容する前提)
- **書き込み先**: `memory/_staging/<id>.json`
- LLM 出力(活動ログ JSON)は pod 側ラッパーが `source: { session_id, range: [start_entry, end_entry] }` を**機械付与**して wrap。LLM には source を推論させない
- **モデル**: `memory.extract_model`。軽量だが文脈理解できる中堅クラス(Haiku / 4o-mini / Flash 相当)を想定
#### Phase 2: 永続化への統合
@@ -63,13 +91,12 @@ agentskills.io の `SKILL.md` 形式は採用しない。Knowledge は `#knowled
- **Trigger**: staging の累積ファイル数 or bytes が閾値超過、または compact 発火時(必ず flush
- **実行主体**: Phase 1 を終えた pod が `memory/_staging/.lock` の advisory file lock を `LOCK_EX | LOCK_NB` で取得試行。取れたら consolidation Worker を spawn。取れなければ skip(他 pod が処理中)
- **Lock**: POSIX `flock(2)` / `fcntl` ベース。プロセスが生きている限り保持、落ちれば OS が自動解放。stale 検出・heartbeat 不要。reasoning 処理が数分〜十数分かかる前提
- **入力**: staging 全件(活動ログ)+ 既存 `memory/*`summary / lessons / decisions / requests / knowledge
- **処理**: sub-Worker に memory read/write tool を渡し、agentic に以下を自律判断:
- 新規 lessons / decisions / requests を 1 件 1 ファイルで追加
- 活動ログから派生する Knowledge(用語定義 / 運用方針 / ルール / 事実 / ノウハウ)を新規作成 or 既存 patch
- **入力**: staging 全件(活動ログ + `source`+ 既存 `memory/*`summary / lessons / decisions / requests / knowledge
- **処理**: sub-Worker に**汎用 CRUD toolfile read / write / edit+ post-write Linter Hook** を渡し、agentic に以下を自律判断:
- 新規 lessons / decisions / requests を 1 件 1 ファイルで追加`sources` は staging の `source` をコピー(LLM 推論ではない)
- 活動ログから派生する Knowledge(用語定義 / 運用方針 / ルール / 事実 / ノウハウ)を新規作成 or 既存 patch`last_sources` を更新
- summary を必要に応じて rewrite
- **書き込み先**: summary / lessons / decisions / requests / knowledge の 5 種
- **Workflow への書き込み禁止**: Phase 2 の write tool schema に workflow を含めないことで構造的に担保(`workflow.md` 参照)
- **書き込み先**: `memory/*` 配下。Workflow 禁止は Linter で担保(`workflow.md` 参照)
- **完了処理**: staging cleanup + lock release。Phase 2 完了時に staging に新着があれば次を発火(Coalesce)
- **モデル**: `memory.consolidation_model`。reasoning 系
@@ -77,8 +104,10 @@ agentskills.io の `SKILL.md` 形式は採用しない。Knowledge は `#knowled
`memory/` 配下は人間も git 経由で編集する。Phase 2 prompt で以下を明示:
- 既存内容を尊重し、**差分追加を優先**する。全文 rewrite は `summary.md` のみ、かつ人間編集と整合する範囲で
- 削除は supersede 記録(`status: superseded` + `superseded_by: <id>`)で表現、直接削除しない
- **rewrite は許可**。既存内容と新規情報を統合・再構成して情報密度を上げることを優先。単純 append(追記で増やすだけ)は避ける
- rewrite 時は**情報損失を最小化**する: 既存の主張・根拠・sources を保持。表現を整理・短縮しても、含まれている要素は落とさない
- 削除は置き換え記録(`status: replaced` + `replaced_by: <slug>`)で表現、直接削除しない
- 人間編集は git diff で顕在化する前提。整合しない rewrite は避け、衝突時は git で解決
#### Offer 経路
@@ -91,13 +120,29 @@ consolidation は自律生成しない。以下は Client に `Event::Notificati
基本分離(memory は独立トリガー、compact は `input_tokens` 既存閾値のまま)。ただし **compact 発火時は Phase 2 を必ず同時 flush**compact で失われる raw を漏らさないため)。
### GC(定期再評価)
Phase 2 とは別経路で memory を再評価し、drop / merge / split / `replaced` chain の整理を行う。Shann³ llm-wiki の lint 相当。Phase 2 は rewrite 許可で情報統合寄りの働きをするが、それでも残る以下の課題の出口として機能する:
- 重要度の低い record が累積する
- 類似 slug が乱立する(Linter Warn で検出したものをまとめて処理)
- `replaced` が溜まり続けて grep / 注入時のノイズになる
- sources 累積
- 長期的に陳腐化した記録の drop
**詳細仕様は後で詰める**(scope 内、未決定)。方針として LLM 駆動の定期ジョブで、Linter Warn 群 + 人間 offer 承認を併用する前提。
### ファイル形式
- frontmatter + Markdown 本文
- Knowledge の frontmatter: `name`, `description`, `auto_invoke`, `user_invocable`
- Lessons / Decisions / Requests の frontmatter: `id`, `created_at`, および種別固有フィールド
- Decisions は `status: open | resolved | superseded`、supersede 時は `superseded_by: <id>` を併記
- Phase 1 staging は `memory/_staging/<id>.json`JSON、1 件 1 ファイル、Phase 2 完了で削除
- frontmatter + Markdown 本文。全 record 共通: `created_at`, `updated_at`
- ファイル名(slug)がそのまま識別子、frontmatter に `id` / `name` field は持たない
- source トレーサビリティ(session log への逆引き、粒度は `session_id` + entry range:
- Lessons / Decisions / Requests: `sources: [{session_id, range: [start, end]}, ...]` 永続化(update 時は追記累積)
- Knowledge: `last_sources: [{session_id, range}, ...]`(最新更新時のみ、過去履歴は git log で追う
- Summary: optional `last_rewritten_from_range`(なしでも可)
- Knowledge 固有: `description`, `auto_invoke`, `user_invocable`
- Decisions 固有: `status: open | resolved | replaced`、置き換え時は `replaced_by: <slug>`
- Phase 1 staging: `memory/_staging/<id>.json`JSON、1 件 1 ファイル、Phase 2 完了で削除。短命なので UUIDv7 可)。pod 側ラッパーが `source` を機械付与して LLM 出力と wrap
- Workflow の frontmatter は `workflow.md` 参照
## Scope 外
@@ -112,7 +157,6 @@ consolidation は自律生成しない。以下は Client に `Event::Notificati
- Phase 2 を担う常駐 daemon 化 — オンデマンド + lock 方式で始める。必要性が出たら upgrade path として daemon 化
- Deterministic promotionOpenClaw 型 scoring + ゲート)— 初期は Phase 2 agent の LLM 判断に委ねる。運用実績で出力を評価してから、成熟カテゴリから scoring 導入
- Shallow request の自動除外判定 — 初期は Phase 1 prompt で「些細な質問は返さなくてよい」と指示する程度。精緻な filter は後
- Retention / GC — Phase 2 agent に直接削除禁止(supersede のみ)を課す一方、明示クリーンアップ経路は未定義。別途 LLM 駆動 GC を用意する前提で、初期は無制限蓄積 + summary rewrite で凌ぐ
### 別 plan / ticket で扱う
+7 -7
View File
@@ -2,15 +2,15 @@
## Context
Workflow は制約付きの強制的な作業フロー。`/workflow-name` で明示的に呼び出し、依存 Knowledge を context に inject してから実行する。Knowledge(`#knowledge-name`)は `docs/plan/memory.md` 側で定義。
Workflow は制約付きの強制的な作業フロー。`/<slug>` で明示的に呼び出し、依存 Knowledge を context に inject してから実行する。Knowledge(`#<slug>`)は `docs/plan/memory.md` 側で定義。
## 決定事項
### 呼び出しと依存
- 呼び出し: `/workflow-name`
- 名前空間はフラット、name は slug(小文字英数とハイフン)
- frontmatter `requires: [knowledge-name, ...]` で依存 Knowledge を name 参照
- 呼び出し: `/<slug>`
- 名前空間はフラット、slug は kebab-case(小文字英数とハイフン)
- frontmatter `requires: [knowledge-slug, ...]` で依存 Knowledge を slug 参照
- 実行時は依存 Knowledge 本文を context に inject してから Workflow 本文を実行
### 呼び出し制御フラグ
@@ -18,15 +18,15 @@ Workflow は制約付きの強制的な作業フロー。`/workflow-name` で明
| フラグ | 意味 | デフォルト |
| ---------------- | ------------------------------------------------------- | ---------- |
| `auto_invoke` | description が LLM context に載り、LLM が自発的に呼べる | **OFF** |
| `user_invocable` | ユーザーが `/` で明示的に呼べる | **ON** |
| `user_invocable` | ユーザーが `/<slug>` で明示的に呼べる | **ON** |
`auto_invoke` の ON 化は人間の判断、または consolidation からの offer 経由のみ。同じ制御は Knowledge 側(`memory.md`)でも採用。
### 格納先とファイル形式
- `memory/workflow/<name>.md`
- `memory/workflow/<slug>.md`(ファイル名 = slug がそのまま識別子、`name` field は持たない)
- frontmatter + Markdown 本文
- frontmatter フィールド: `name`, `description`, `auto_invoke`, `user_invocable`, `requires`
- frontmatter フィールド: `description`, `auto_invoke`, `user_invocable`, `requires`
### 生成・更新ポリシー