memory実装チケット
This commit is contained in:
parent
89c2c701fd
commit
123fc3b0ad
12
TODO.md
12
TODO.md
|
|
@ -1,4 +1,3 @@
|
|||
- [ ] テスト設計 → [tickets/test-design.md](tickets/test-design.md)
|
||||
- [ ] Agent Skills サポート → [tickets/agent-skills.md](tickets/agent-skills.md)
|
||||
- [ ] ツール設計
|
||||
- [ ] Bash ツール (Permission 層と統合) → [tickets/bash-tool.md](tickets/bash-tool.md)
|
||||
|
|
@ -9,3 +8,14 @@
|
|||
- [ ] TUI 拡充
|
||||
- [ ] フルスクリーン化によるオーバーホール → [tickets/tui-fullscreen-overhaul.md](tickets/tui-fullscreen-overhaul.md)
|
||||
- [ ] 新しい Pod を spawn する UI の設計 → [tickets/tui-pod-spawn-ui.md](tickets/tui-pod-spawn-ui.md)
|
||||
- [ ] サブミット入力
|
||||
- [ ] protocol Segment 化 → [tickets/submit-segment-protocol.md](tickets/submit-segment-protocol.md)
|
||||
- [ ] TUI 補完 + 型付き atom 化 → [tickets/submit-tui-completion.md](tickets/submit-tui-completion.md)
|
||||
- [ ] メモリ機構
|
||||
- [ ] ファイル形式 + Linter 土台 → [tickets/memory-file-format.md](tickets/memory-file-format.md)
|
||||
- [ ] memory / Knowledge 検索ツール → [tickets/memory-search-tools.md](tickets/memory-search-tools.md)
|
||||
- [ ] `model_invokation: ON` の常駐注入 → [tickets/memory-resident-injection.md](tickets/memory-resident-injection.md)
|
||||
- [ ] Phase 1 活動抽出 → [tickets/memory-phase1-extract.md](tickets/memory-phase1-extract.md)
|
||||
- [ ] Phase 2 consolidation → [tickets/memory-phase2-consolidation.md](tickets/memory-phase2-consolidation.md)
|
||||
- [ ] 使用頻度メトリクス + Knowledge 化候補レポート → [tickets/memory-usage-metrics.md](tickets/memory-usage-metrics.md)
|
||||
- [ ] GC(定期再評価) → [tickets/memory-gc.md](tickets/memory-gc.md)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ Workflow(`/<slug>` で呼び出される制約付き作業フロー)は別 p
|
|||
- 同主題の 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 対象外、参照経路のみ
|
||||
- Raw session log は既存 `session-store` で保持する。memory 対象外、参照経路のみ
|
||||
|
||||
### Knowledge の呼び出し制御
|
||||
|
||||
|
|
|
|||
244
docs/research/llm-worker-vs-rust-llm-libs.md
Normal file
244
docs/research/llm-worker-vs-rust-llm-libs.md
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
# `llm-worker` vs Rust LLM ライブラリ群 比較レポート
|
||||
|
||||
調査日: 2026-04-26
|
||||
対象: `crates/llm-worker` (本プロジェクト) / `rig` / `genai` / `swiftide`
|
||||
|
||||
調査方法: 各リポジトリを external checkout で取得し、ソース(README, Cargo.toml, src/, examples/)を直接読解。
|
||||
|
||||
---
|
||||
|
||||
## 0. TL;DR
|
||||
|
||||
```
|
||||
低レイヤ ←──────────────────────────────────────→ 高レイヤ
|
||||
HTTP wrapper Worker/Loop Agent Framework Pipeline/RAG
|
||||
───────────── ──────────── ──────────────── ──────────────
|
||||
genai ●●●●● (out-of-scope)
|
||||
llm-worker ●●●●● (一部)
|
||||
rig ●●● ●●●●● ●●●
|
||||
swiftide ●● ●●●● ●●●●● (主軸)
|
||||
```
|
||||
|
||||
- **`genai`** … マルチプロバイダの「統一 chat client」。エージェントループ・状態管理は明示的にスコープ外。
|
||||
- **`llm-worker`** … Worker = 「LLM 対話の中央実行器」。低レベル(HTTP)と高レベル(Agent / RAG / Pipeline)の中間に位置するレイヤを精緻に作っている。
|
||||
- **`rig`** … Agent / Tool / Pipeline / VectorStore を一通り揃えた汎用フレームワーク。Provider 数とエコシステムが最大の武器。
|
||||
- **`swiftide`** … 一次目的はストリーミング Indexing / Query パイプライン。Agent はあとから足された二の矢で、`async-openai` / `async-anthropic` をラップ。
|
||||
|
||||
要点: **`llm-worker` の独自性は「型状態でのキャッシュ保護」「Interceptor による上位層への決定委譲」「Prune を context projection として非破壊で扱う」の 3 点**。これらは他 3 者の誰も持っていない。一方、Provider カバレッジ・VectorStore・Pipeline DAG では rig に大差で負ける。
|
||||
|
||||
---
|
||||
|
||||
## 1. スコープ宣言(各プロジェクトが自分を何と呼んでいるか)
|
||||
|
||||
| プロジェクト | 自称 | 提供する | 提供しない(明示・暗黙) |
|
||||
|---|---|---|---|
|
||||
| **llm-worker** | "LLM との対話を管理する低レベル基盤クレート" | Worker による turn 実行、Tool 実行、stream イベント、Interceptor、cache 保護 | RAG / Embedding / VectorStore / Pipeline DAG / 永続化 |
|
||||
| **rig** | "Ergonomic & modular library for building LLM applications" | Agent / Tool / Pipeline / Vector / Embedding / OTel | (ほぼ全部入り。明示的な non-goal は薄い) |
|
||||
| **genai** | "Standardizing chat completion APIs across major AI services" | Chat (sync/stream)、Tool 定義、Embedding | **Agent loop / 会話状態管理を明示的に out-of-scope** |
|
||||
| **swiftide** | "Fast, streaming indexing, query, and agentic LLM applications" / "data pipeline" | Indexing pipeline / Query state machine / Agent / Hook | (LLM HTTP は外部 SDK = `async-openai` 等に委譲) |
|
||||
|
||||
`llm-worker` のスコープ宣言は他より控えめで、「何かの上位層から呼ばれる前提」が読み取れる(`Interceptor` の存在がそれを裏付ける)。
|
||||
|
||||
---
|
||||
|
||||
## 2. レイヤ階層と被り
|
||||
|
||||
`Worker` が担っているレイヤを基準にすると、各プロジェクトの「同じ層」と「上下層」は次のように整理できる。
|
||||
|
||||
### 同じ層(== 競合)
|
||||
|
||||
| 機能 | llm-worker | rig | genai | swiftide |
|
||||
|---|---|---|---|---|
|
||||
| Provider 抽象 (HTTP) | ◎ 自前 (4) | ◎ 自前 (20+) | ◎ 自前 (18+) | ○ 外部 SDK ラップ |
|
||||
| Streaming イベント正規化 | ◎ | ◎ | ◎ | ○ |
|
||||
| Tool 定義 + 実行ループ | ◎ | ◎ | △ (定義のみ、loop は呼び出し側) | ◎ |
|
||||
| Multi-turn loop | ◎ | ◎ | ✕ | ◎ |
|
||||
| Hook / Interceptor | ◎ Interceptor + closure | ◎ PromptHook | △ Resolver のみ | ◎ 6+ Hook |
|
||||
| 履歴管理 | ◎ Item / ContentPart | ◎ Message | △ ChatRequest を呼び出し側で append | ◎ MessageHistory trait |
|
||||
|
||||
### 上下層(== 補完関係)
|
||||
|
||||
| 機能 | llm-worker | rig | genai | swiftide |
|
||||
|---|---|---|---|---|
|
||||
| Embedding / VectorStore | ✕ | ◎ 10+ | △ (Embed のみ) | ◎ 9+ |
|
||||
| RAG | ✕ | ◎ | ✕ | ◎ |
|
||||
| Pipeline DAG | ✕ | ◎ `parallel!` / `try_op` | ✕ | ◎ Indexing pipeline |
|
||||
| 永続化 | ✕ | △ | ✕ | ◎ MessageHistory swap |
|
||||
| OTel / Observability | △ tracing のみ | ◎ GenAI Semantic Conv | △ | ◎ Langfuse 等 |
|
||||
| 型状態でのキャッシュ保護 | **◎ 唯一** | ✕ | ✕ | ✕ |
|
||||
|
||||
---
|
||||
|
||||
## 3. コアの抽象を並べる
|
||||
|
||||
### `llm-worker::Worker<C, S>`
|
||||
- `C: LlmClient`(プロバイダ)、`S: WorkerState`(`Mutable` | `Locked` の sealed trait)
|
||||
- ライフサイクル: `Mutable` で履歴/プロンプト編集 → `lock()` → `Locked` で `run()` / `resume()` → `unlock()` で戻る
|
||||
- `state.rs:1-61`: `Locked` 中は履歴 append-only、`set_system_prompt` 等は型レベルで呼べない
|
||||
- `prune.rs:66-118`: `prunable_indices()` + `project()` で context のみ縮約。永続履歴は不変 = "context projection"
|
||||
|
||||
### `rig::Agent` + `PromptRequest`
|
||||
- 状態機械型: `max_turns`、`extended_details()` で usage / message tracking
|
||||
- `PromptHook` trait: `on_completion_call`, `on_completion_response`, `on_tool_call` (skip 可), `on_tool_result`, `on_text_delta`, …
|
||||
- `ToolSet` + `ToolEmbedding` で RAG 可能なツール
|
||||
- Pipeline DAG: `Op` trait + `parallel!` macro
|
||||
|
||||
### `genai::Client`
|
||||
- `exec_chat(model, ChatRequest, options) -> ChatResponse`
|
||||
- `ChatStreamEvent { Start, Chunk, ReasoningChunk, ToolCallChunk, End }`
|
||||
- Adapter pattern: `to_web_request_data` / `to_chat_response` / `to_chat_stream`
|
||||
- モデル名の prefix で provider 推論 (`gpt-` → OpenAI, `claude-` → Anthropic)
|
||||
- 状態管理は呼び出し側(`ChatRequest` を毎ターン clone & append)
|
||||
|
||||
### `swiftide-agents::Agent`
|
||||
- Builder: `llm`, `context`, `tools`, `toolboxes`, `hooks`
|
||||
- `AgentContext` trait + `DefaultContext` (AtomicUsize で completions ポインタ管理)
|
||||
- State enum: `Pending` / `Running` / `Stopped(StopReason)`
|
||||
- Tool execution: `LocalExecutor` と MCP (Model Context Protocol)
|
||||
- Provider 層は `async-openai` 0.33+ / `async-anthropic` 0.6 を流用
|
||||
|
||||
---
|
||||
|
||||
## 4. 三大独自点(`llm-worker` だけが持っているもの)
|
||||
|
||||
### 4.1 型状態によるキャッシュ保護 — `state::WorkerState`
|
||||
|
||||
```
|
||||
Worker<C, Mutable> Worker<C, Locked>
|
||||
├─ history_mut() ✓ ├─ history_mut() ✗ (compile error)
|
||||
├─ set_system_prompt() ✓ ├─ set_system_prompt() ✗
|
||||
├─ register_tool() ✓ ├─ run() / resume() ✓
|
||||
└─ lock() ─────────────────→ │
|
||||
└─ unlock() ──────────→ Mutable
|
||||
```
|
||||
|
||||
- **何を防ぐか**: KV cache の prefix が変わるような編集を `Locked` 中に行うこと(=次の `run()` で cache miss を引く事故)
|
||||
- **誰がやっているか**: rig / genai / swiftide のいずれもキャッシュ整合性は「呼び出し側のお気持ち」レベル。genai は `CacheControl::Ephemeral / Stable` enum を持つが、それはマーク用であって状態機械ではない
|
||||
- **意義**: production の Anthropic / OpenAI prompt cache 利用で、誤った `set_system_prompt` が静かに課金を倍増させる事故を**コンパイル時に潰せる**
|
||||
|
||||
### 4.2 Interceptor による上位層への決定委譲 — `interceptor.rs`
|
||||
|
||||
`Interceptor` trait が持つフック点:
|
||||
- `on_prompt_submit` → `PromptAction`
|
||||
- `pre_llm_request` → `PreRequestAction`
|
||||
- `pre_tool_call` → `PreToolAction`
|
||||
- `post_tool_call` → `PostToolAction`
|
||||
- `on_turn_end` → `TurnEndAction`
|
||||
|
||||
**rig の `PromptHook` との違い**: rig のフックは「観察 + skip/abort のフラグ」。`llm-worker` は **戻り値が ActionEnum** で、上位層が次の挙動を選択できる(例: `PreToolAction::Override(custom_result)`)。これは `Worker` を「自律ループ」と「上位 orchestrator から駆動される実行器」の両方として使える設計上の選択。
|
||||
|
||||
### 4.3 Context Projection による prune — `prune.rs`
|
||||
|
||||
- 削るのは `Item::ToolResult { content }` の中身だけ。`Item` 自体は履歴に残す(summary は維持)
|
||||
- `project()` は **イミュータブル変換** で永続履歴を変えない
|
||||
- savings 推定は意図的に上位層に委譲(`prune.rs` 末尾コメント)
|
||||
- swiftide も MessageHistory に `Summary` メッセージで似たことをやるが、**永続履歴を直接置換**する方式。`llm-worker` の方が rollback / 再生 / debugging に強い
|
||||
|
||||
---
|
||||
|
||||
## 5. 各競合の「これは llm-worker に勝っている」点
|
||||
|
||||
### rig
|
||||
- **Provider 数**: 20+(OpenAI / Anthropic / Gemini / Bedrock / Vertex / Azure / Groq / DeepSeek / Cohere / Mistral / OpenRouter / Together / xAI / Perplexity / HuggingFace …)
|
||||
- **VectorStore**: MongoDB / LanceDB / Neo4j / Qdrant / SQLite / SurrealDB / Milvus / ScyllaDB / S3Vectors / HelixDB
|
||||
- **Pipeline DAG**: `parallel!` macro / `try_op` / agent_ops(Agent を Op として組み立て可能)
|
||||
- **OTel**: GenAI Semantic Convention に完全準拠
|
||||
- **WASM**: `rig-core` のみ WASM 互換
|
||||
- **更新頻度**: 直近 20 commit が 1〜2 週間以内
|
||||
|
||||
### genai
|
||||
- **Provider 数**: 18+
|
||||
- **薄さ**: 6,539 LOC / 35 deps で multi-provider client が完成している(`llm-worker` の `llm_client/` は 1.5k LOC で 4 provider)
|
||||
- **Native protocol サポート**: Anthropic reasoning, Gemini thinking, OpenAI strict mode, OpenAI Responses API の `previous_response_id`/`store` を素通し
|
||||
- **Tool call streaming**: `ToolCallChunk` が分離イベント
|
||||
- **Resolver** で auth / model / endpoint をフレキシブルに差し替え
|
||||
|
||||
### swiftide
|
||||
- **Indexing pipeline**: streaming loader → transformer → chunker → storage の fluent パイプライン
|
||||
- **Query state machine**: Pending → Retrieved → Answered の型状態(くしくも型状態だが対象が違う)
|
||||
- **Hook 粒度**: `before_all` / `before_completion` / `after_completion` / `before_tool` / `after_tool` / `on_new_message` / `on_stop` 等 6+
|
||||
- **MCP サポート**: ToolExecutor として LocalExecutor と MCP の両方
|
||||
- **MessageHistory trait** で永続化バックエンド(Redis 等)に差し替え可能
|
||||
- **既存 SDK の活用**: `async-openai` / `async-anthropic` をベースに薄く乗せる戦略
|
||||
|
||||
---
|
||||
|
||||
## 6. 各競合の「これは llm-worker の方が良い」点
|
||||
|
||||
### vs rig
|
||||
- **キャッシュ整合性**: rig は `extended_details()` で usage を観測できるが、prefix 変更を**防止**するメカニズムはない
|
||||
- **依存の薄さ**: rig-core 25.5K LOC + 大量 sub-crate vs llm-worker 5.8K LOC
|
||||
- **Worker の単一責務**: rig の `Agent` は LLM 呼び出し + Tool + (optional) RAG までを抱え込む。`llm-worker` は orchestrator を分離
|
||||
|
||||
### vs genai
|
||||
- **Tool 実行ループ**: genai は呼び出し側で書く必要がある(README/example で明示)
|
||||
- **会話履歴の構造化**: genai は `ChatRequest` を毎ターン clone する素朴な API
|
||||
- **Interceptor**: genai は `Resolver` で初期化時のカスタマイズのみ。実行中フックなし
|
||||
|
||||
### vs swiftide
|
||||
- **Provider 直接実装**: swiftide は `async-openai` 0.33 / `async-anthropic` 0.6 に依存しており、その上流に出来る/出来ないが縛られる。`llm-worker` は HTTP まで自前で握る
|
||||
- **Agent loop の中核設計**: swiftide-agents は `DefaultContext` の AtomicUsize ベースで素朴。型状態保護なし
|
||||
- **依存の少なさ**: swiftide-agents 単体でも `async-openai` を呼ぶ前提
|
||||
|
||||
---
|
||||
|
||||
## 7. 「ライブラリ化したとき競合するか」の解像度
|
||||
|
||||
| 相手 | 競合度 | 理由 |
|
||||
|---|---|---|
|
||||
| **rig** | 🟥 高 | 同じ "agent + tool + multi-provider" を狙う層。rig は既にエコシステムを持っており、正面衝突は不利 |
|
||||
| **genai** | 🟨 中 | 層が違う(client vs worker)。むしろ `llm-worker` の `llm_client/` を捨てて genai に乗る選択肢がある |
|
||||
| **swiftide** | 🟩 低 | 一次目的が違う(pipeline)。agent の中核実行を `llm-worker` に置き換える "embed" 戦略すら成立し得る |
|
||||
|
||||
---
|
||||
|
||||
## 8. ポジショニング案(仮にライブラリ化するなら)
|
||||
|
||||
`llm-worker` がぶつからない・かつ需要がある場所を考えると、次のような立ち位置が現実的:
|
||||
|
||||
> **"Production-grade LLM worker primitive — 型状態でキャッシュ整合性を守り、Interceptor で上位層 (rig / swiftide / 自社 orchestrator) から駆動できる低レベル実行器"**
|
||||
|
||||
具体的な打ち出し方:
|
||||
1. **キャッシュ整合性をコンパイル時に保証する唯一のクレート** という明確な売り文句。Anthropic の prompt cache 課金事故で困った人を狙う
|
||||
2. **Tool 実行ループ + Interceptor** をプリミティブとして提供し、上位フレームワークから plug できることを主張
|
||||
3. **HTTP まで自前** はやめて、`llm_client/` を外す or feature 化し、`genai` バックエンドを optional 提供する選択肢も検討に値する(実装コストを 1.5k LOC 削れる)
|
||||
4. **Pipeline / RAG / VectorStore は提供しない** ことを明示。rig / swiftide の代替を狙わないことで、共存ストーリーが書ける
|
||||
|
||||
---
|
||||
|
||||
## 9. ライブラリ化の判断材料(再)
|
||||
|
||||
- **需要がある層か**: yes。rig / swiftide / genai は揃って "もう一段下のキャッシュ整合性プリミティブ" を持っていない
|
||||
- **既存と被るか**: 上記 3 案でかわせる
|
||||
- **維持コスト**: API 安定化 + provider 追従が恒常的に乗る。`llm_client/` を外すか genai に寄せるかでだいぶ軽くなる
|
||||
- **タイミング**: insomnia 本体がリリースされ、`Worker` の API が stress test を受ける前に公開すると、後から破壊的変更を強いられる。**先に insomnia をリリースして、production 使用例として参照させてからライブラリ化する**方が安全
|
||||
|
||||
---
|
||||
|
||||
## 付録: 主要ファイルへの参照
|
||||
|
||||
### llm-worker
|
||||
- `crates/llm-worker/src/lib.rs:1-59` — モジュール構成
|
||||
- `crates/llm-worker/src/worker.rs:101-191` — Worker<C, S>
|
||||
- `crates/llm-worker/src/state.rs:1-61` — Mutable / Locked 型状態
|
||||
- `crates/llm-worker/src/interceptor.rs:1-147` — Interceptor trait
|
||||
- `crates/llm-worker/src/prune.rs:66-118` — context projection
|
||||
- `crates/llm-worker/src/llm_client/{auth,client,event,transport,types}.rs`
|
||||
- `crates/llm-worker/src/tool_server.rs:27-52` — Deferred 登録
|
||||
|
||||
### rig
|
||||
- `github.com/0xPlaygrounds/rig/rig/rig-core/src/{agent,completion,tool,pipeline,vector_store,streaming}/mod.rs`
|
||||
|
||||
### genai
|
||||
- `github.com/jeremychone/rust-genai/src/lib.rs:1-25`
|
||||
- `.../src/client/client_impl.rs:62-67`
|
||||
- `.../src/chat/chat_request.rs:10-34`
|
||||
- `.../src/chat/chat_stream.rs:11-86`
|
||||
- `.../src/adapter/adapter_types.rs:11-59`
|
||||
|
||||
### swiftide
|
||||
- `github.com/bosun-ai/swiftide/swiftide-agents/src/agent.rs:45-100`
|
||||
- `.../swiftide-agents/src/hooks.rs`
|
||||
- `.../swiftide-core/src/chat_completion/traits.rs`
|
||||
- `.../swiftide-indexing/src/pipeline.rs`
|
||||
- `.../swiftide-query/src/`
|
||||
74
tickets/memory-file-format.md
Normal file
74
tickets/memory-file-format.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# メモリ機構: ファイル形式 + Linter 土台
|
||||
|
||||
## 背景
|
||||
|
||||
`docs/plan/memory.md` で決めたメモリ機構の永続化レイヤの土台。`memory/*` と `knowledge/*` の record を保存・編集する際の静的スキーマと、汎用 CRUD への post-write Hook として挟む Linter を成立させる。Phase 1/2、検索ツール、常駐注入、GC はすべてこの層に乗る。
|
||||
|
||||
Workflow(`docs/plan/workflow.md`)も同じ frontmatter / Linter 経路で扱うため、`memory/workflow/<slug>.md` の frontmatter 検証と書き込み制限も本チケットに含める。実行経路(`/<slug>` dispatch)は別。
|
||||
|
||||
## 要件
|
||||
|
||||
### ディレクトリと record 種別
|
||||
|
||||
- `memory/summary.md` — Always-on サマリ(1 ファイル固定)
|
||||
- `memory/decisions/<slug>.md` — Decisions
|
||||
- `memory/requests/<slug>.md` — Requests
|
||||
- `memory/workflow/<slug>.md` — Workflow(frontmatter 検証のみ対象)
|
||||
- `memory/_staging/<id>.json` — Phase 1 中間(本チケットはパス予約と Linter 対象外化のみ)
|
||||
- `knowledge/<slug>.md` — Knowledge(`memory/` の兄弟)
|
||||
|
||||
slug は kebab-case(小文字英数とハイフン)。ファイル名がそのまま識別子で、frontmatter に `id` / `name` は持たない。
|
||||
|
||||
### frontmatter スキーマ
|
||||
|
||||
種別ごとの必須フィールドは `docs/plan/memory.md` §ファイル形式 / §書き込み経路と Linter の表に従う。具体的な必須項目:
|
||||
|
||||
- 共通: `created_at`, `updated_at`
|
||||
- Decisions: `sources`, `status: open | resolved | replaced`、置き換え時 `replaced_by: <slug>`
|
||||
- Requests: `sources`
|
||||
- Knowledge: `kind`, `description`, `model_invokation`, `user_invocable`, `last_sources`
|
||||
- Summary: `updated_at`(optional: `last_rewritten_from_range`)
|
||||
- Workflow: `description`, `auto_invoke`, `user_invocable`, `requires`
|
||||
|
||||
### Linter ルール
|
||||
|
||||
静的 error(post-write Hook が turn を戻し、sub-Worker に自己修正させる。N 回失敗で abort):
|
||||
|
||||
- frontmatter 必須 field 欠落・型違反
|
||||
- `memory/workflow/` への書き込み禁止(sub-Worker のみ。人間編集は対象外)
|
||||
- 同 slug での新規作成禁止(既存があれば update に切り替えるサイン)
|
||||
- `#<slug>` / `replaced_by: <slug>` / `requires: [..]` が実在 record を指す
|
||||
- Decisions `status` の enum 違反
|
||||
- `model_invokation: true` な Knowledge の description 1024 chars 上限
|
||||
- 種別ごとの char 硬上限(具体値は設定ファイルで tune)
|
||||
|
||||
膨張抑制 Warn(error ではなく改善ヒント):
|
||||
|
||||
- 低重要度 × char の天秤
|
||||
- `sources` 配列長の累積
|
||||
- 類似 slug 乱立
|
||||
|
||||
### 適用経路
|
||||
|
||||
- sub-Worker の汎用 CRUD(read/write/edit)への post-write Hook として挟む
|
||||
- 人間編集(エディタ / git commit)に対しても同一ルールで検証できる CLI または pre-commit hook 経路を用意(詳細は実装で判断、結果として同じルールが一箇所で定義されていること)
|
||||
|
||||
## 範囲外
|
||||
|
||||
- 検索ツール、常駐注入、Phase 1/2、GC の実装
|
||||
- 意味破壊(rewrite で主張が落ちる等)の検出 — 監査 LLM 層は将来検討
|
||||
- staging JSON の schema — Phase 1 チケット
|
||||
- Workflow の `/<slug>` 実行経路
|
||||
|
||||
## 完了条件
|
||||
|
||||
- 上記パスに手で record を置いて Linter を走らせると、スキーマ違反 / 参照切れ / 同 slug 競合が error として返る
|
||||
- sub-Worker が CRUD で書き込んだ際、違反時は turn が戻り自己修正が走る
|
||||
- Warn は error を止めず、出力されることが確認できる
|
||||
- `memory/workflow/` への sub-Worker からの書き込みは error で止まり、人間編集は通る
|
||||
- 既存ビルド・テストを壊さない
|
||||
|
||||
## 参照
|
||||
|
||||
- `docs/plan/memory.md` §ファイル形式 / §書き込み経路と Linter / §Knowledge の採択基準
|
||||
- `docs/plan/workflow.md` §格納先とファイル形式 / §生成・更新ポリシー
|
||||
61
tickets/memory-gc.md
Normal file
61
tickets/memory-gc.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# メモリ機構: GC(定期再評価)
|
||||
|
||||
## 背景
|
||||
|
||||
`docs/plan/memory.md` §GC の実装。Phase 2 は情報統合寄りだが、それでも残る重要度低下・類似 slug 乱立・`replaced` 滞留・sources 累積・現状不整合を整理する定期再評価経路。人間 offer はかけず、結果は git diff で検証する建て付け。
|
||||
|
||||
保護閾値は使用頻度メトリクスの明示 invoke frequency に依存する。
|
||||
|
||||
## 要件
|
||||
|
||||
### Trigger
|
||||
|
||||
- 定期実行(累積 input token ベース推奨、具体値は設定で tune、実装判断)
|
||||
|
||||
### 実行主体と渡すツール
|
||||
|
||||
- GC Agent が spawn
|
||||
- Phase 2 と同じ汎用 CRUD + 検索ツール + post-write Linter Hook
|
||||
- 入力: GC 対象 record 群 + Linter Warn + 使用頻度メトリクス + `replaced` chain + sources 過多情報
|
||||
|
||||
### 操作粒度
|
||||
|
||||
- ファイル単位: 丸ごと drop / 複数ファイル merge / 1 ファイルの split
|
||||
- ファイル内部分: 節・箇条の削除 or 圧縮、`sources` 古いエントリの trim
|
||||
|
||||
### 評価カテゴリ
|
||||
|
||||
`outdated`, `superseded`, `unused`, `noisy` を GC 理由の分類として使う。record に一律の「stale」フラグは付けない。drop / merge / split / trim / rewrite のどれを選ぶかをこのカテゴリで説明可能にする。
|
||||
|
||||
### 判断ルール
|
||||
|
||||
- 保護閾値: **明示 invoke** の `frequency >= 1.0 invokes/Mtoken` の record は drop / 大幅圧縮の対象外
|
||||
- 初期値 1.0、workspace 設定でカスタマイズ可
|
||||
- `model_invokation` 注入による常駐は計数対象外(別指標として参照のみ)
|
||||
- 単一 record が複数カテゴリに該当してもよい
|
||||
- 直接削除してよいが、誤判定しやすいものは merge / trim を優先(prompt 側で誘導)
|
||||
|
||||
### prompt
|
||||
|
||||
- `docs/plan/memory-prompts.md` §GC prompt に従う
|
||||
|
||||
## 範囲外
|
||||
|
||||
- 監査 LLM 層(将来検討)
|
||||
- Vector index / FTS5 導入(将来検討、GC 判断には影響しない)
|
||||
- Workflow の GC 対象化(初期は触らない)
|
||||
|
||||
## 完了条件
|
||||
|
||||
- Trigger で GC Agent が走り、不要 record が整理される
|
||||
- Linter Warn で検出した類似 slug 乱立などが GC でまとめて収斂する
|
||||
- 保護閾値超過 record が drop / 大幅圧縮から外れる
|
||||
- 置き換えは `status: replaced` + `replaced_by` で残り、直接削除と区別可能
|
||||
- git diff で drop / merge / split / trim / rewrite の理由が読める
|
||||
|
||||
## 参照
|
||||
|
||||
- `docs/plan/memory.md` §GC / §使用頻度メトリクス / §判断ルール
|
||||
- `docs/plan/memory-prompts.md` §GC prompt
|
||||
- `tickets/memory-phase2-consolidation.md`(ツール構成の共通化)
|
||||
- `tickets/memory-usage-metrics.md`(保護閾値の依存)
|
||||
56
tickets/memory-phase1-extract.md
Normal file
56
tickets/memory-phase1-extract.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# メモリ機構: Phase 1 活動抽出
|
||||
|
||||
## 背景
|
||||
|
||||
`docs/plan/memory.md` §Phase 1 の実装。activity tokens の累積閾値で発火し、前回 Phase 1 以降の session log 範囲から「起きたこと」を 4 種の活動ログ候補として抽出、`memory/_staging/<id>.json` に書き出す。Knowledge 化や summary rewrite は Phase 2 に委ねる。
|
||||
|
||||
Pod を立てずに既存 compact と同じ Worker spawn 機構を再利用する。raw session log は `session-store` で保持されており、ここから range を切り出して入力に使う。
|
||||
|
||||
## 要件
|
||||
|
||||
### Trigger
|
||||
|
||||
- activity tokens 累積閾値(設定ファイルで tune)
|
||||
- tool call カウントは不採用(ツールカスタマイズ非依存・大小重みづけのため)
|
||||
|
||||
### 実行主体と入出力
|
||||
|
||||
- 既存 compact の Worker spawn 機構を再利用、Pod は立てない
|
||||
- 入力: 前回 Phase 1 以降の session log 範囲(処理済み境界 pointer は session 側に保持、寿命を session と揃える)
|
||||
- 出力 JSON schema: `decisions`, `discussions`, `attempts`, `requests` の候補配列。抽出対象なしは空配列
|
||||
- 出力に自由文の補足説明を入れさせない(schema 準拠のみ)
|
||||
|
||||
### 書き込み
|
||||
|
||||
- 書き込み先: `memory/_staging/<id>.json`(1 件 1 ファイル、UUIDv7 可)
|
||||
- pod 側ラッパーが `source: { session_id, range: [start_entry, end_entry] }` を**機械付与**して LLM 出力と wrap
|
||||
- LLM に source を推論させない
|
||||
|
||||
### モデル
|
||||
|
||||
- 設定 key `memory.extract_model`(軽量だが文脈理解できる中堅クラス想定)
|
||||
|
||||
### prompt
|
||||
|
||||
- prompt 要件は `docs/plan/memory-prompts.md` §Phase 1: 活動抽出 prompt に従う
|
||||
|
||||
## 範囲外
|
||||
|
||||
- Phase 2 による staging の消費・クリーンアップ(別チケット)
|
||||
- staging の cleanup 戦略の詳細(Phase 2 で完了時に消す、実行中追加分は残す、という契約だけ本チケットで守る)
|
||||
- compact Worker spawn 機構自体の拡張(既存をそのまま使う。共通化が必要になったら別途)
|
||||
|
||||
## 完了条件
|
||||
|
||||
- Pod 稼働中に閾値超過で Phase 1 が発火し、`memory/_staging/<id>.json` にファイルができる
|
||||
- ファイルは schema に準拠、`source` が機械付与されている
|
||||
- 抽出対象なしのときは空配列として書き出される(または発火そのものを skip、どちらでもよい)
|
||||
- session 側の処理済み pointer が更新され、次回 Phase 1 は続きから走る
|
||||
- 既存 compact の動作に回帰がない
|
||||
|
||||
## 参照
|
||||
|
||||
- `docs/plan/memory.md` §Phase 1: 活動抽出 / §ファイル形式(staging)
|
||||
- `docs/plan/memory-prompts.md` §共通原則 / §Phase 1: 活動抽出 prompt
|
||||
- 既存 `session-store` クレート(session log range 取得)
|
||||
- 既存 compact の Worker spawn 経路
|
||||
80
tickets/memory-phase2-consolidation.md
Normal file
80
tickets/memory-phase2-consolidation.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# メモリ機構: Phase 2 consolidation
|
||||
|
||||
## 背景
|
||||
|
||||
`docs/plan/memory.md` §Phase 2 の実装。staging の活動ログ + 既存 `memory/*` + Knowledge 化候補レポートを入力に、consolidation Worker が汎用 CRUD + 検索ツール + Linter Hook で agentic に統合する。Phase 1 を終えた pod が spawn し、並走防止は staging 配下の進行状況ファイルで担保する。
|
||||
|
||||
Knowledge 新規作成は「候補レポート掲載の source から派生する場合」に限る。使用頻度メトリクス(候補レポートの集計元)が未完のうちは、レポートは空入力として動作し、Phase 2 は decisions / requests / summary / 既存 Knowledge update のみ行う。
|
||||
|
||||
## 要件
|
||||
|
||||
### Trigger
|
||||
|
||||
- staging の累積ファイル数 or bytes 閾値(設定で tune)
|
||||
- compact 発火時に必ず flush(compact で失われる raw を漏らさない)
|
||||
|
||||
### 実行主体と入力
|
||||
|
||||
- Phase 1 を終えた pod が consolidation Worker を spawn
|
||||
- 起動時スナップショットで consumed ID list を確定
|
||||
- 入力:
|
||||
- consumed ID 分の staging エントリ(活動ログ + `source`)
|
||||
- 既存 `memory/*`(summary / decisions / requests)全文
|
||||
- Knowledge 化候補レポート(メトリクスチケットの成果物。未完のうちは空)
|
||||
- 既存 `knowledge/*` は prompt に埋めず、Knowledge 検索ツール経由で agent が引く
|
||||
|
||||
### 渡すツール
|
||||
|
||||
- 汎用 CRUD(file read / write / edit)
|
||||
- memory 検索ツール
|
||||
- Knowledge 検索ツール
|
||||
- post-write Linter Hook(違反時 turn 戻し、N 回失敗 abort)
|
||||
|
||||
### 処理内容
|
||||
|
||||
- 新規 decisions / requests を 1 件 1 ファイルで追加、`sources` は staging の `source` をコピー(LLM 推論ではない)
|
||||
- 活動ログから派生する Knowledge を新規作成 or 既存 patch。**新規作成は候補レポート掲載の source 由来に限る**
|
||||
- summary を必要に応じて rewrite(1-5k tokens 目安)
|
||||
- 削除は `status: replaced` + `replaced_by: <slug>` で置き換え記録、直接削除しない
|
||||
- 書き込み先: `memory/*`, `knowledge/*`。`memory/workflow/` は Linter で弾かれる
|
||||
|
||||
### 並走防止
|
||||
|
||||
- staging 配下に 1 ファイル(Pod 識別子 + consumed ID list)
|
||||
- 存在し、示された Pod が動作している間、そのプロセスが排他占有
|
||||
- 実行中に Phase 1 が追加した staging は触らず、次回 Phase 2(Coalesce)に委ねる
|
||||
- 完了時は consumed ID list の staging のみ cleanup、追加分は残す
|
||||
- Phase 2 完了時に staging 新着があれば次を発火(Coalesce)
|
||||
- 占有の実現方法(pid 存在確認 / flock / 他)は実装判断
|
||||
|
||||
### モデル
|
||||
|
||||
- 設定 key `memory.consolidation_model`(reasoning 系)
|
||||
|
||||
### prompt
|
||||
|
||||
- `docs/plan/memory-prompts.md` §共通原則 / §Phase 2: 統合 prompt / §Phase 2: Knowledge 書き込み prompt に従う
|
||||
|
||||
## 範囲外
|
||||
|
||||
- 使用頻度メトリクスと Knowledge 化候補レポートの集計(別チケット。未完の間は空レポートで動作)
|
||||
- GC(別チケット)
|
||||
- Workflow 関連の offer(別チケット、Notification 経路が先)
|
||||
- 意味破壊検出の監査 LLM 層(将来検討)
|
||||
|
||||
## 完了条件
|
||||
|
||||
- Phase 1 が staging に残した活動ログを Phase 2 が `memory/*` / `knowledge/*` に統合する
|
||||
- Linter 違反時は turn が戻り、sub-Worker が自己修正する
|
||||
- 並走防止ファイルが想定通り機能し、複数 Phase 2 の重複起動が防げる
|
||||
- Coalesce で実行中追加分が次回に引き継がれる
|
||||
- compact 発火時に Phase 2 が flush される
|
||||
- 空レポートでも新規 Knowledge を作らずに動く(decisions / requests / summary / 既存 Knowledge update のみ)
|
||||
|
||||
## 参照
|
||||
|
||||
- `docs/plan/memory.md` §Phase 2 / §Phase 2 agent への原則 / §Compact との関係
|
||||
- `docs/plan/memory-prompts.md` §Phase 2 関連
|
||||
- `tickets/memory-file-format.md`(Linter)
|
||||
- `tickets/memory-search-tools.md`(検索ツール)
|
||||
- `tickets/memory-phase1-extract.md`(staging 生産)
|
||||
32
tickets/memory-resident-injection.md
Normal file
32
tickets/memory-resident-injection.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# メモリ機構: `model_invokation: ON` の常駐注入
|
||||
|
||||
## 背景
|
||||
|
||||
`docs/plan/memory.md` §retrieval 経路 の「常駐注入」項目。`model_invokation: ON` な Knowledge record の description を通常 Pod の system prompt に載せ、モデルが必要と判断した時点で検索ツール経由で本文を引く形を成立させる。Phase 2 Pod には注入しない。
|
||||
|
||||
専用の auto-invoke 経路は用意しない。モデルが description を見て自発的に検索ツールを呼ぶ経路に一本化する。
|
||||
|
||||
## 要件
|
||||
|
||||
- Pod 起動時に `knowledge/*` を走査し、`model_invokation: ON` の record の description を system prompt に連結
|
||||
- Phase 2 Pod では注入しない(consolidation は検索ツール経由で自律探索)
|
||||
- 予算はシステムプロンプト全体予算に含める。`memory/summary.md` の 5k 枠とは別管理にしない
|
||||
- 超過時の件数キャップ / 優先順位ルールは初期不要(description 1024 chars 上限で通常は収まる前提)。ON record 数が増えて問題になったら別チケットで対応
|
||||
|
||||
## 範囲外
|
||||
|
||||
- auto-invoke 用の別経路(採用しない)
|
||||
- ON/OFF 切替の自動判定(初期は手動。将来検討)
|
||||
- Workflow 側の `auto_invoke` 同等機能 — 仕様対称だが本チケットは Knowledge のみ
|
||||
|
||||
## 完了条件
|
||||
|
||||
- `model_invokation: true` の knowledge を置いた状態で通常 Pod を起動すると、system prompt に description が含まれる
|
||||
- `model_invokation: false` のものは含まれない
|
||||
- Phase 2 Pod では注入されない
|
||||
- 既存の system prompt 構成(AGENTS.md / scope summary / skills 等)と共存する
|
||||
|
||||
## 参照
|
||||
|
||||
- `docs/plan/memory.md` §retrieval 経路 / §Knowledge の呼び出し制御
|
||||
- `tickets/memory-file-format.md`(依存: `model_invokation` frontmatter)
|
||||
51
tickets/memory-search-tools.md
Normal file
51
tickets/memory-search-tools.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# メモリ機構: memory / Knowledge 検索ツール
|
||||
|
||||
## 背景
|
||||
|
||||
`docs/plan/memory.md` §retrieval 経路 で定義した 2 本の検索ツールを Pod から呼べる LLM ツールとして実装する。memory 検索と Knowledge 検索は対象ディレクトリが違うだけで同型の仕様。grep ベースで始め、FTS / vector は将来検討。
|
||||
|
||||
このツールは Phase 2 Pod の agentic 探索経路としても、通常 Pod の `#<slug>` 展開経路としても、使用頻度メトリクスの観測点としても使う(メトリクスの hook 挿入は本チケットの範囲外、経路だけ揃える)。
|
||||
|
||||
## 要件
|
||||
|
||||
### ツール仕様(両者共通)
|
||||
|
||||
- Input:
|
||||
- `query: string`(自由文字列、必須)
|
||||
- `slug: string`(完全一致 1 件返し、`#<slug>` 解決に使う)
|
||||
- `kind: string`(Knowledge のみ、filter)
|
||||
- Output: `{ slug, kind, description, model_invokation, excerpt }` の配列
|
||||
- `excerpt` はマッチ箇所の前後数行
|
||||
- ソート: grep 出現順(初期)
|
||||
- ヒット件数上限と excerpt 行数は設定ファイルで tune
|
||||
- 対象ファイルは都度スキャン。派生 index は持たない
|
||||
|
||||
### 対象
|
||||
|
||||
- memory 検索: `memory/{summary,decisions,requests}/*.md`(workflow / \_staging は除外)
|
||||
- Knowledge 検索: `knowledge/*.md`
|
||||
|
||||
### 登録
|
||||
|
||||
- 通常 Pod と Phase 2 Pod の両方に渡せる tool 定義
|
||||
- Phase 2 Pod には Knowledge 検索を必ず渡す(全 Knowledge 本文を prompt に埋めない前提)
|
||||
|
||||
## 範囲外
|
||||
|
||||
- 使用頻度メトリクス本体(hook 点の予約のみ。カウント・レポートは別チケット)
|
||||
- slug サジェスト補完 UI(TUI 側、別途)
|
||||
- FTS / vector index
|
||||
- 常駐注入(別チケット)
|
||||
|
||||
## 完了条件
|
||||
|
||||
- 通常 Pod / Phase 2 Pod 双方から両ツールが呼べる
|
||||
- `slug` 指定で完全一致の 1 件が返り、`#<slug>` の本文展開経路として成立する
|
||||
- `query` 指定で frontmatter 含む全文から excerpt 付きでヒットが返る
|
||||
- Knowledge 検索の `kind` filter が効く
|
||||
- 対象外ディレクトリ(`memory/workflow/`, `memory/_staging/`)はヒットしない
|
||||
|
||||
## 参照
|
||||
|
||||
- `docs/plan/memory.md` §retrieval 経路 / §Knowledge の採択基準
|
||||
- `tickets/memory-file-format.md`(依存: frontmatter スキーマ)
|
||||
60
tickets/memory-usage-metrics.md
Normal file
60
tickets/memory-usage-metrics.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# メモリ機構: 使用頻度メトリクス + Knowledge 化候補レポート
|
||||
|
||||
## 背景
|
||||
|
||||
`docs/plan/memory.md` §使用頻度メトリクス の実装。memory 検索ツール / Knowledge 検索ツール内に invoke 計測フックを入れ、時間単位ではなく累積 input token で正規化した頻度を算出する。Phase 2 の Knowledge 新規作成 gate と GC の保護閾値の両方で使われる。
|
||||
|
||||
## 要件
|
||||
|
||||
### 観測経路
|
||||
|
||||
- memory 検索ツール / Knowledge 検索ツール内に hook を挿入
|
||||
- `#<slug>`(slug 完全一致経路)、`/<slug>`(workflow 側、将来接続)、明示検索呼び出しをすべて同じ経路に集約
|
||||
|
||||
### カウント対象
|
||||
|
||||
- **明示 invoke**: 検索ツール経由の読み取り / `#<slug>` / `/<slug>` を `n回 / Mtoken` でスコア化
|
||||
- **`model_invokation` 注入**: 明示 invoke の分子には含めない。**コスト側**(注入した record に対する消費 input tokens)として別途記録。使われ率 ratio や ON/OFF 判断材料として後段で参照
|
||||
- ファイル token 数
|
||||
|
||||
### 記録先
|
||||
|
||||
- staging と独立
|
||||
- workspace 側に記録(session データ喪失で統計が消えない)
|
||||
- invoke event を UUID + Stats 形式
|
||||
- 具体 schema / フォーマットは実装で決定
|
||||
|
||||
### 集計
|
||||
|
||||
- 累積方式: 最大 10 回前の invoke から現在までの時系列窓でフィルタして集計
|
||||
- **Knowledge 化候補レポート**:
|
||||
- 対象は `memory/*` 配下の record(Phase 1 成果物の decisions / requests + 既存 knowledge)
|
||||
- 明示 invoke 頻度が閾値超過のものを列挙
|
||||
- 同一 session 内の連続参照は 1 count に丸める
|
||||
- 複数 session での再参照を要件とする(spike 除外)
|
||||
- 閾値は設定ファイルで tune
|
||||
|
||||
### 消費者
|
||||
|
||||
- Phase 2 Worker の入力として候補レポートを渡す
|
||||
- GC Agent の保護閾値判定(明示 invoke frequency >= 1.0 invokes/Mtoken)
|
||||
|
||||
## 範囲外
|
||||
|
||||
- GC の実装本体(別チケット。本チケットは保護閾値判定に必要なメトリクスの提供まで)
|
||||
- `model_invokation` ON/OFF の自動判定ロジック(将来検討)
|
||||
- Shallow request の自動除外(将来検討)
|
||||
|
||||
## 完了条件
|
||||
|
||||
- 検索ツール呼び出しで invoke event が workspace 側に積まれる
|
||||
- `model_invokation` 注入のコスト側集計が別口で積まれる
|
||||
- 候補レポート API が Phase 2 Worker の起動時に呼べる
|
||||
- 閾値未満の record は候補レポートに載らない
|
||||
- 同一 session 内連続参照は 1 count に丸まる
|
||||
|
||||
## 参照
|
||||
|
||||
- `docs/plan/memory.md` §使用頻度メトリクス / §判断ルール / §retrieval 経路
|
||||
- `tickets/memory-search-tools.md`(hook 挿入点)
|
||||
- `tickets/memory-phase2-consolidation.md`(消費者)
|
||||
81
tickets/submit-segment-protocol.md
Normal file
81
tickets/submit-segment-protocol.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# サブミット入力: protocol Segment 化
|
||||
|
||||
## 背景
|
||||
|
||||
現状の `Method::Run { input: String }` はユーザー入力を素の文字列で運んでいる。TUI の `Atom::Paste`(bracketed paste で受けた塊)は表示用には `[Clipboard #N | X chars, Y lines]` ラベルを持っているが、submit 時に `InputBuffer::submit_text` で flatten され、Pod や session log にはただの長い user message として伝わる。
|
||||
|
||||
memory / workflow 導入に伴い、submit には paste 以外にも以下を載せたくなる:
|
||||
|
||||
- `@<path>` のファイル参照 + auto_read
|
||||
- `#<slug>` の Knowledge 参照(`docs/plan/memory.md`)
|
||||
- `/<slug>` の Workflow 起動(`docs/plan/workflow.md`)
|
||||
|
||||
これを protocol 上で **String + marker パース**で扱うと、Pod が正規表現と escape 規則を抱え、code block 内の `#foo` を literal にするか等の ambiguity と escape 漏洩が常に付きまとう。さらにリッチクライアント(GUI / web / ネイティブ)はファイル添付や paste を file chip / clipboard card として描くため、protocol が String だと「chip → string marker → Pod で再 parse → 表示用に再構築」という 3 段 round-trip を全 client で再実装する形になる。
|
||||
|
||||
protocol を typed segment の列に上げると、Pod は parser を持たず resolve に集中でき、client は自分の表現単位のまま intent を送れる。最低限 `Segment::Text(String)` を fallback として置くので、CLI piping 等の dumb client は 1 segment を作るだけで従来通り動く(protocol の dictation が「Text を作れること」に閉じる)。
|
||||
|
||||
## 要件
|
||||
|
||||
### protocol
|
||||
|
||||
`Method::Run` の payload を `String` から `Vec<Segment>` に置き換える。Segment は最低限以下の variant を持つ:
|
||||
|
||||
- `Text` — 自由文字列。dumb client の fallback
|
||||
- `Paste` — TUI 等の bracketed paste 由来の塊。`id` と本文を持つ
|
||||
- `FileRef` — `@<path>` の auto_read 対象
|
||||
- `KnowledgeRef` — `#<slug>` の Knowledge 参照
|
||||
- `WorkflowInvoke` — `/<slug>` の Workflow 起動
|
||||
|
||||
`Event::UserMessage` の payload も同じ `Vec<Segment>` に揃え、複数 client で見たり log replay する際に typed のまま再構築できる状態にする。
|
||||
|
||||
未知 variant に対する forward compatibility(`#[serde(other)]` 相当の吸収)を入れる。
|
||||
|
||||
### Pod 側 resolve
|
||||
|
||||
Pod は `Vec<Segment>` を LLM context へ flatten する単一経路を持つ:
|
||||
|
||||
- `Text` → そのまま
|
||||
- `Paste` → 本文を inline 展開(現状 TUI が flatten してきたのと同じ結果)。**session log / Event::UserMessage 上ではラベル化情報を保持**し、表示時に `[Clipboard #N | X chars]` を再構築できること
|
||||
- `FileRef` → scope 内なら本文 read + inline、scope 外は明示エラー
|
||||
- `KnowledgeRef` / `WorkflowInvoke` → resolver が登録されていれば展開、未登録はフォールバック(後述)
|
||||
|
||||
resolver の trait 化と memory / workflow 用 resolver 実装は別チケット。本チケットは **Text と Paste を typed のまま end-to-end で運び切る経路**で完結させる。`FileRef` 以降は variant 定義と「resolver 未登録時のフォールバック」だけ仕込んで実装は後続に委ねる。
|
||||
|
||||
### TUI 側
|
||||
|
||||
`InputBuffer::Atom::Paste` を submit 時に flatten せず、`Segment::Paste` として送出する。`Event::UserMessage` を typed segment で受けて `Block::UserMessage` を typed のまま描画(paste は引き続き magenta ラベル)。
|
||||
|
||||
text しか作れない client が引き続き存在しても良いことを protocol 仕様に明記する(`vec![Segment::Text(_)]` のみで動く)。
|
||||
|
||||
### unknown variant / 未登録 resolver の扱い(要決定)
|
||||
|
||||
新 variant を持つ client が古い Pod に投げる、または resolver 未登録の variant を Pod が受けるケースの挙動を本チケットで決める。候補:
|
||||
|
||||
- (a) 黙って drop — 静かに情報が落ちて user/LLM 双方が気付けない
|
||||
- (b) `[unknown input: kind=foo]` 相当の placeholder を LLM context に差し込み、LLM が気づいて指摘できる
|
||||
- (c) hard error で submit 拒否
|
||||
|
||||
(b) を仮の第一候補として実装方針を詰める。serde 側は unknown variant を吸収する形を初期から入れる。
|
||||
|
||||
## 範囲外
|
||||
|
||||
- `@` / `#` / `/` token の TUI parsing と補完 UI(`tickets/submit-tui-completion.md`)
|
||||
- KnowledgeRef / WorkflowInvoke の resolver 実装(memory / workflow チケット)
|
||||
- FileRef の引数拡張(行範囲、glob 等)
|
||||
|
||||
## 完了条件
|
||||
|
||||
- `Method::Run` / `Event::UserMessage` が `Vec<Segment>` で wire を通る
|
||||
- TUI から paste した内容が `Segment::Paste` で送出され、Pod の LLM context では本文展開、Event 経由の再描画では `[Clipboard #N | ...]` が復元される
|
||||
- `vec![Segment::Text(_)]` だけ送る client は従来通り動く
|
||||
- 未登録 variant の扱いが決定済みルール通りに動く(決定は本チケット内で合意)
|
||||
- forward compat: 未知 variant を含む payload を deserialize しても panic / parse error にならない
|
||||
- 既存ビルド・テストを壊さない
|
||||
|
||||
## 参照
|
||||
|
||||
- `docs/plan/memory.md` §retrieval 経路 / §Knowledge の呼び出し制御
|
||||
- `docs/plan/workflow.md` §呼び出しと依存
|
||||
- `crates/protocol/src/lib.rs`(`Method::Run`, `Event::UserMessage`)
|
||||
- `crates/tui/src/input.rs`(`Atom::Paste`, `submit_text`)
|
||||
- `crates/tui/src/app.rs`(`submit_input`, `Block::UserMessage` 描画)
|
||||
61
tickets/submit-tui-completion.md
Normal file
61
tickets/submit-tui-completion.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# サブミット入力: TUI 補完 + 型付き atom 化
|
||||
|
||||
## 背景
|
||||
|
||||
`tickets/submit-segment-protocol.md` で protocol が `Vec<Segment>` を運べるようになった前提で、TUI 側に「`@` / `#` / `/` を打鍵中に候補を出し、確定したら typed atom (= 送出時の `Segment`) に昇格させる」UX を載せる。
|
||||
|
||||
`@` / `#` / `/` は TUI の入力アフォーダンスであって protocol contract ではない(GUI などは同じ intent をボタンや picker で表す)。本チケットは TUI 限定の UX に閉じる。
|
||||
|
||||
## 要件
|
||||
|
||||
### token 検出と昇格
|
||||
|
||||
入力中に prefix を検出して候補を浮かせる:
|
||||
|
||||
- `@<部分パス>` — workspace 内のファイル / ディレクトリ候補
|
||||
- `#<部分slug>` — Knowledge slug
|
||||
- `/<部分slug>` — Workflow slug + client-side コマンド(`/clear` など)
|
||||
|
||||
確定(Tab / Enter 等、入力 UX の詳細は実装で)で対象範囲を `Atom::FileRef` / `Atom::KnowledgeRef` / `Atom::WorkflowInvoke` の indivisible atom に置き換える。挙動は既存の `Atom::Paste` と同等(cursor は中に入れない、Backspace で塊ごと削除)。submit 時に対応する `Segment` 変種に変換して送る。
|
||||
|
||||
### 候補列挙のための protocol query
|
||||
|
||||
補完用に Pod へ問い合わせる軽量経路を追加:
|
||||
|
||||
- ファイル候補(scope 内、prefix マッチ)
|
||||
- Knowledge / Workflow slug 候補(kind 指定 + prefix マッチ)
|
||||
|
||||
`Event` ストリームに載せる性質ではないため、request/response 形式を新設する(具体形式は実装で判断、既存 `Method` の枠に増やすか別経路を作るかも実装側で決める)。
|
||||
|
||||
### 表示
|
||||
|
||||
確定後の atom は paste と同じ「indivisible chip」スタイルで描画する。`@` / `#` / `/` ごとに色を変える程度の差異化を入れる。`Block::UserMessage` 側でも同一スタイルで再描画する(`Event::UserMessage` が typed segment で来る前提)。
|
||||
|
||||
### client-side `/<slug>` の dispatch
|
||||
|
||||
`/clear` のような client 完結コマンドは Pod に送らず TUI 内で処理する。TUI 内に簡易な dispatch 表を持ち、未知の `/<slug>` は `Segment::WorkflowInvoke` として送る。初期 dispatch 表は `/clear` 程度で良く、拡張は別途。
|
||||
|
||||
## 範囲外
|
||||
|
||||
- Pod 側の resolver 実装(memory / workflow チケット)
|
||||
- 候補スコアリング、fuzzy search、preview 等の高度な補完体験
|
||||
- リッチクライアント(GUI / web)の同等 UX
|
||||
|
||||
## 完了条件
|
||||
|
||||
- `@` / `#` / `/` を打鍵すると候補が出て、確定で chip 化される
|
||||
- chip 化された atom が対応する `Segment` として Pod に送出され、`Event::UserMessage` で戻ってきた typed segment が同じ見た目で再描画される
|
||||
- 候補列挙の query / response が wire を通る
|
||||
- `/clear` が client-side で処理され、Pod には届かない
|
||||
- 既存ビルド・テストを壊さない
|
||||
|
||||
## 依存
|
||||
|
||||
- `tickets/submit-segment-protocol.md`
|
||||
|
||||
## 参照
|
||||
|
||||
- `crates/tui/src/input.rs`(`Atom` 体系の拡張)
|
||||
- `crates/tui/src/app.rs`(`submit_input`、`Block::UserMessage` 描画)
|
||||
- `docs/plan/memory.md` §retrieval 経路(slug 補完対象)
|
||||
- `docs/plan/workflow.md` §呼び出しと依存
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# テスト設計
|
||||
|
||||
## 背景
|
||||
|
||||
各クレートのテスト方針が未策定。クレート間の依存関係と非同期処理が絡むため、
|
||||
テストの層(単体/結合/E2E)と mock 境界を明確にする必要がある。
|
||||
|
||||
## 検討事項
|
||||
|
||||
低層部分のテストを信頼し、上層までモックデータを引っ張ってきてテストする必要は無いのか?
|
||||
実際の認証を使ったE2Eはどの様に結果を出すか?/
|
||||
Loading…
Reference in New Issue
Block a user