diff --git a/TODO.md b/TODO.md index 6d9ce196..a6e4b7e5 100644 --- a/TODO.md +++ b/TODO.md @@ -9,7 +9,6 @@ - [ ] TUI 拡充 - [ ] フルスクリーン化によるオーバーホール → [tickets/tui-fullscreen-overhaul.md](tickets/tui-fullscreen-overhaul.md) - [ ] Run 中の入力キューイング → [tickets/tui-input-queue.md](tickets/tui-input-queue.md) - - [ ] ホームディレクトリ配下の整理 → [tickets/home-dir-layout.md](tickets/home-dir-layout.md) - [ ] ユーザーマニフェストのモデル設定 wizard → [tickets/tui-user-model-setup.md](tickets/tui-user-model-setup.md) - [ ] サブミット入力 - [ ] TUI 補完 + 型付き atom 化 → [tickets/submit-tui-completion.md](tickets/submit-tui-completion.md) diff --git a/tickets/home-dir-layout.md b/tickets/home-dir-layout.md deleted file mode 100644 index 7fe577da..00000000 --- a/tickets/home-dir-layout.md +++ /dev/null @@ -1,113 +0,0 @@ -# ホームディレクトリ配下のディレクトリ整理 - -## 背景 - -現状、Insomnia のホーム配下のファイルは 2 つのツリーに分かれていて、規約が一貫していない: - -- `$XDG_CONFIG_HOME/insomnia/` (fallback `~/.config/insomnia/`) - - `manifest.toml` (user manifest) - - `providers.toml` / `models.toml` (catalog user override) - - `prompts/` / `prompts.toml` (user prompts) -- `~/.insomnia/` - - `sessions/` (session store) - - `run/` (XDG_RUNTIME_DIR 不在時の socket fallback) - -実態としては「config は XDG 尊重、data / runtime は `~/.insomnia/`」というハイブリッド構成だが、 - -- ロジックが 11 箇所に分散していて (`pod/src/main.rs` / `pod/src/runtime/dir.rs` / `pod/src/runtime/scope_lock.rs` / `tui/src/main.rs` / `manifest/src/cascade.rs` / `provider/src/catalog.rs` / `pod/src/factory.rs` 等)、`default_runtime_dir` (main.rs) と `default_base` (dir.rs) のように完全重複しているものもある -- すべて `std::env::var()` の手作業実装で、XDG 解決ライブラリ (`dirs` / `directories` 等) は未導入 -- どこに何を置くかが docs にも module comment にも明記されていない -- テストでパス上書きの手段が統一されておらず、`unsafe std::env::set_var` を多用、`scope_lock.rs` には並行テスト用 `ENV_LOCK: Mutex` まで存在する -- 既存の override 環境変数は `INSOMNIA_SCOPE_LOCK` (scope.lock 単体)しかなく、テスト/開発用に統一された口がない - -新しい機能(モデル設定 wizard 等)を足す前に、レイアウトの規約と解決ロジックを 1 箇所に集約する。 - -## 方針 - -### レイアウト: 案 C (ハイブリッド、現状追認) - -config 系は XDG、data / runtime 系は `~/.insomnia/` 配下を維持。`XDG_CONFIG_HOME` / `XDG_RUNTIME_DIR` を既に尊重しており、現状の動作を壊さない: - -``` -$XDG_CONFIG_HOME/insomnia/ # 人が編集する設定 (fallback ~/.config/insomnia/) - manifest.toml - providers.toml - models.toml - prompts/ - prompts.toml -~/.insomnia/ # プログラムが書くデータ・ランタイム - sessions/ - run/ # XDG_RUNTIME_DIR があればそちら優先 -``` - -`$XDG_DATA_HOME` / `$XDG_STATE_HOME` には対応しない(必要になったら別途検討)。 - -### ロジック集約: paths モジュール - -パス解決を 1 箇所に集約する。crate は新設せず、`crates/manifest` 配下に `paths` module を追加して全 crate からそれを参照する形にする (manifest crate は既に pod / tui / provider から依存されている)。 - -集約対象: - -- `pod/src/main.rs:default_store_dir` (sessions) -- `pod/src/main.rs:default_runtime_dir` と `pod/src/runtime/dir.rs:default_base` (重複) -- `pod/src/runtime/scope_lock.rs:default_lock_path` -- `tui/src/main.rs:resolve_socket` -- `manifest/src/cascade.rs:user_manifest_path` -- `provider/src/catalog.rs:user_override_path` -- `pod/src/factory.rs` の user/project prompts dir 導出 - -`paths` module は以下のような API を提供する想定(命名は実装時に確定): - -- `config_dir()` → `$XDG_CONFIG_HOME/insomnia` or `~/.config/insomnia` -- `data_dir()` → `~/.insomnia` -- `runtime_dir()` → `$XDG_RUNTIME_DIR/insomnia` or `~/.insomnia/run` -- 各 well-known file への getter (`user_manifest_path()`, `sessions_dir()`, `scope_lock_path()`, `socket_path(pod_name)` 等) - -### 環境変数の整理 - -現状散らばっている override を整理する: - -| 変数 | 現状 | 新方針 | -|---|---|---| -| `INSOMNIA_HOME` | 無し | **新設**。設定すると config_dir / data_dir / runtime_dir すべての base になる(テスト・開発・ポータブル運用向けの統一 override) | -| `INSOMNIA_CONFIG_DIR` | 無し | **新設**。config_dir の個別 override (INSOMNIA_HOME より優先) | -| `INSOMNIA_DATA_DIR` | 無し | **新設**。data_dir の個別 override | -| `INSOMNIA_RUNTIME_DIR` | 無し | **新設**。runtime_dir の個別 override | -| `INSOMNIA_SCOPE_LOCK` | scope.lock の path 直接指定 (テスト用) | **廃止**。`INSOMNIA_RUNTIME_DIR` で代替 | -| `INSOMNIA_POD_COMMAND` | 子 Pod 起動コマンド | **存続**(パス系ではない) | -| `INSOMNIA_API_KEY_*` | scheme 別の認証 env | **存続**(パス系ではない) | -| `XDG_CONFIG_HOME` | 尊重 | 引き続き尊重 (INSOMNIA_* 系より低優先) | -| `XDG_RUNTIME_DIR` | 尊重 | 引き続き尊重 (INSOMNIA_* 系より低優先) | - -優先順位: `INSOMNIA__DIR` > `INSOMNIA_HOME` > `XDG_*` > 既定 (`~/.config/insomnia` または `~/.insomnia`) - -`INSOMNIA_HOME` 導入によりテストでの `unsafe std::env::set_var("XDG_CONFIG_HOME", ...)` を `INSOMNIA_HOME=tempdir` で置き換えられるようになる(`scope_lock.rs:980` の `ENV_LOCK` Mutex も整理可)。 - -### マイ採用しないション - -レイアウトは現状追認なので、既存ユーザの自動移行は不要。`INSOMNIA_SCOPE_LOCK` の廃止のみ、削除時に release notes で告知する(テスト用なので外部利用想定はほぼ無い)。 - -## 完了条件 - -- `crates/manifest/src/paths.rs` (仮) に config / data / runtime の各責務と解決ロジックがまとめられ、module コメントで「どこに何が置かれるか」が明記されている -- 既存の 11 箇所のパス解決が新 module の API 呼び出しに置き換わっている(特に `default_runtime_dir` と `default_base` の重複が解消されている) -- `INSOMNIA_HOME` / `INSOMNIA_CONFIG_DIR` / `INSOMNIA_DATA_DIR` / `INSOMNIA_RUNTIME_DIR` の override が動作し、優先順位が決まっている -- `INSOMNIA_SCOPE_LOCK` が削除され、テストは `INSOMNIA_HOME` か `INSOMNIA_RUNTIME_DIR` 経由に書き換わっている -- `unsafe std::env::set_var` を使っているテスト箇所が、新 override に対応した最小限の数まで減っている -- pod の起動と tui の spawn flow が引き続き動作する - -## 範囲外 - -- Windows / macOS のネイティブ規約(`%APPDATA%` / `~/Library/Application Support` 等)への対応。本チケットは Linux / 一般的な Unix 想定 -- `$XDG_DATA_HOME` / `$XDG_STATE_HOME` への対応(必要になったら別途) -- TUI 側で setup wizard が「どこに何を書く」表示するかの UX。本チケットの結論を `tickets/tui-user-model-setup.md` が前提として使う - -## 後続チケット - -- `tickets/tui-user-model-setup.md`: 本チケットで確定したレイアウトに従って user manifest を書き込む wizard を実装する - -## Review - -- 状態: Approve -- レビュー詳細: [./home-dir-layout.review.md](./home-dir-layout.review.md) -- 日付: 2026-04-27 diff --git a/tickets/home-dir-layout.review.md b/tickets/home-dir-layout.review.md deleted file mode 100644 index a1f1b846..00000000 --- a/tickets/home-dir-layout.review.md +++ /dev/null @@ -1,44 +0,0 @@ -# Review: ホームディレクトリ配下のディレクトリ整理 - -レビュー対象: HEAD (`915061f home-dirの整理`)。 - -## 前提・要件の確認 - -- **paths.rs に config/data/runtime の責務と解決ロジックが集約され、module コメントで配置が明記**: 満たされている。`crates/manifest/src/paths.rs:1-25` に三つのベースディレクトリの責務、解決順マトリクス、`INSOMNIA_HOME` 設定時の `$X/config` `$X` `$X/run` 各サブツリーへの集約が表で示されている。`config_dir` / `data_dir` / `runtime_dir` と well-known file getter (`user_manifest_path`, `user_prompts_dir`, `user_pack_file`, `user_catalog_override`, `sessions_dir`, `scope_lock_path`, `pod_runtime_dir`, `pod_socket_path`) が揃っている。 -- **既存 11 箇所の置換 / `default_runtime_dir` と `default_base` の重複解消**: 満たされている。 - - `pod/src/main.rs:99-101` `paths::sessions_dir()`、`pod/src/main.rs:137-146` `paths::runtime_dir()` で旧 `default_store_dir` / `default_runtime_dir` を完全削除 (`git diff HEAD~1 HEAD -- crates/pod/src/main.rs` で確認済み)。 - - `pod/src/runtime/dir.rs:122-130` `default_base` は `paths::runtime_dir()` の薄いラッパに変わり、`main.rs` との重複が解消されている。 - - `pod/src/runtime/scope_lock.rs:69-77` `default_lock_path` は `paths::scope_lock_path()` のラッパ。 - - `pod/src/factory.rs:111-118` で `paths::user_manifest_path` / `user_prompts_dir` / `user_pack_file` を直接利用。 - - `tui/src/main.rs:32-38` `resolve_socket` は `paths::pod_socket_path()` 経由。 - - `provider/src/catalog.rs:160,193` で `paths::user_catalog_override` を利用。 - - `manifest/src/cascade.rs` から `user_manifest_path` 削除、`manifest/src/lib.rs:9` で `pub use paths::user_manifest_path` の互換 re-export。 -- **`INSOMNIA_HOME` / `INSOMNIA_CONFIG_DIR` / `INSOMNIA_DATA_DIR` / `INSOMNIA_RUNTIME_DIR` の優先順位**: `paths.rs:30-68` の各関数と `paths.rs:199-292` のテストで `INSOMNIA__DIR > INSOMNIA_HOME > XDG_* > 既定` の順位が網羅的にカバーされている (`config_dir_explicit_wins_over_insomnia_home`, `config_dir_insomnia_home_outranks_xdg`, `runtime_dir_insomnia_home_is_run_subdir`, etc.)。 -- **`INSOMNIA_SCOPE_LOCK` の廃止**: 完了。production / test 両方の grep で 0 ヒット (`tickets/home-dir-layout.md` 内の歴史的記述のみ残る)。`scope_lock.rs:545-1126` のテストは `RuntimeDirSandbox` (`INSOMNIA_RUNTIME_DIR` + `INSOMNIA_HOME` / `XDG_RUNTIME_DIR` の退避) に置換済み。 -- **`unsafe std::env::set_var` を使うテスト箇所が最小限**: 妥当な水準まで縮小。`paths.rs` 12 件・`scope_lock.rs` 3 ブロック (set/remove)・`catalog.rs` 2 件・統合テスト 3 本 (各 EnvGuard + 個別 set_var) と、いずれも env override の RAII guard か serial gate を経由しており、共有ヘルパに収斂されている。元の `scope_lock.rs:980` のような scope_lock 直書きは消えた。env を弄らないと `INSOMNIA_RUNTIME_DIR` 等の優先順位を検証できないため「最小限」の解釈として妥当。 -- **pod 起動 / TUI spawn flow が動作**: `cargo build --workspace` / `cargo test --workspace` 通過の旨をユーザー側で確認済みと申告 (本レビューでは再実行せず)。コードパスは旧実装と論理同型のラッパに置換されているため、機能後退の余地は小さい。 - -## アーキテクチャ・スコープ - -- 集約先の選定 (新 crate を作らず `manifest::paths`) は memory `feedback_llm_worker_scope` / `feedback_crate_naming` の方針に整合。`manifest` crate は既に provider / pod / tui から依存されており、追加の依存グラフ歪みが発生していない。 -- API 形状は **「ベース 3 つ + well-known ファイルの getter」** の薄い層に留めており、I/O やディレクトリ作成・存在検査を `paths` 側で握り込んでいない。実際の作成・検査は呼び出し側 (`scope_lock.rs:101-122` `LockFileGuard::open`, `RuntimeDir::create_default`, etc.) に残っているので、テストでの差し替えやサンドボックス運用が壊れない。 -- `INSOMNIA_HOME` のレイアウトマッピング (`config = $X/config`, `data = $X` 直, `runtime = $X/run`) は、案 C (XDG_CONFIG_HOME 尊重 + `~/.insomnia/` を data/runtime) と整合。テスト用途では「単一 tempdir に三系統が同居する」直感も保たれている。 -- 範囲外 (Windows / `XDG_DATA_HOME` / `XDG_STATE_HOME`) には手を出していない。YAGNI を守れている。 -- `manifest/src/lib.rs:9` の `pub use paths::user_manifest_path` は、cascade.rs から関数を消した互換維持で、ext crate の API 壊しを避けている。狙いは合理的。 - -## 指摘事項 - -### Non-blocking / Follow-up - -- ドキュメント未追従 (本チケットの完了条件外だが、後続のために notes): `docs/architecture.md:90,97,108,122`、`docs/pod-factory.md:16,79,183`、`docs/plan/llm_providers.md:47`、`crates/pod/src/prompt/loader.rs:8` が `$XDG_CONFIG_HOME/insomnia/...` / `$XDG_RUNTIME_DIR/insomnia/scope.lock` を直接書いており、`INSOMNIA_HOME` / `INSOMNIA_CONFIG_DIR` 系の override に触れていない。誤りではない (その経路は今も既定として有効) が、後続の `tickets/tui-user-model-setup.md` で wizard が「どこに書くか」を表示する際、ドキュメント側の表記も `manifest::paths` を起点にする方が一貫する。本チケットでは敢えて手を入れていないが、次にこの周辺を触る時にまとめて差し替えるのが自然。 -- `paths::data_dir` は env が完全に何も無い場合でも `HOME` だけは要求する設計だが、`INSOMNIA_DATA_DIR` 単独設定で `HOME` 不在のケースはちゃんと拾う (`paths.rs:46-52`)。一方 `data_dir` には `XDG_DATA_HOME` のフォールスルーが無く、ticket の方針 (`$XDG_DATA_HOME` 非対応) どおりだが、将来同変数を採用する際の差分位置は `data_dir` の 2 行目になる旨をコメントしておくと意図が伝わりやすい。 -- `paths::pod_socket_path` の doc コメント (`paths.rs:108-113`) は「Pod プロセスは `RuntimeDir::socket_path()` 経由で作成する」と外部からの予測 API である旨を明示しており良い。一方 `RuntimeDir::socket_path()` 側 (`crates/pod/src/runtime/dir.rs:99-101`) には逆参照が無いため、相互コメントを足すと将来の混乱予防になる (Nit に近い)。 - -### Nits - -- `paths.rs:121-126` の `env_path` ヘルパは `std::env::var(name).ok().filter(...)` で、`Err(NotPresent)` と `Err(NotUnicode)` を共に未設定として扱う。後者は実用上ほぼ起きないが、tracing で warn を出す価値はある — ただし本チケットの責務外なので強制ではない。 -- `pod/src/main.rs:100` の `unwrap_or_else(|| PathBuf::from(".insomnia/sessions"))` フォールバック (env 全滅時の相対パス退避) は、後続の `FsStore::new` で cwd 起点の相対書き出しになるため挙動が読みにくい。`runtime_dir` 側 (`main.rs:137-146`) のように early-error にするか、コメントで意図 (どうせ HOME も無い極端な構成: テスト harness のごく一部) を一行入れると良い。実害は無いので Nit。 - -## 判断 - -**Approve** — チケットの 6 つの完了条件すべてに対して具体的な根拠が確認でき、コードベースの歪みも観測されない。`paths` モジュールは責務分離・優先順位・テストカバレッジの三点で過剰でも不足でもなく、後続の `tui-user-model-setup` 等が乗ってくる土台として妥当。ドキュメント追従は本チケットの責務外として Follow-up に分類。