home-dir-layout修正
This commit is contained in:
parent
8658845b02
commit
8cf0bd6374
|
|
@ -105,10 +105,12 @@ pub fn pod_runtime_dir(pod_name: &str) -> Option<PathBuf> {
|
|||
Some(runtime_dir()?.join(pod_name))
|
||||
}
|
||||
|
||||
/// `<runtime_dir>/<pod_name>/sock` — Pod の Unix socket パス (TUI が
|
||||
/// attach 時に使う)。Pod プロセスが実際に socket を作成するのは
|
||||
/// `RuntimeDir::socket_path()` 経由だが、外部からの予測はこの関数で
|
||||
/// 行う。
|
||||
/// `<runtime_dir>/<pod_name>/sock` — Pod の Unix socket パス。
|
||||
///
|
||||
/// Pod プロセス内で実際に socket を作成するのは `pod` crate の
|
||||
/// `RuntimeDir::socket_path()` で、Pod 名が分かっている外部 (TUI の
|
||||
/// attach フロー等) からの**予測**はこの関数で行う。両者は同じパス
|
||||
/// を返すことが期待される。
|
||||
pub fn pod_socket_path(pod_name: &str) -> Option<PathBuf> {
|
||||
Some(pod_runtime_dir(pod_name)?.join("sock"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,10 +95,24 @@ async fn main() -> ExitCode {
|
|||
}
|
||||
};
|
||||
|
||||
// Initialize persistent store
|
||||
let store_dir = cli.store.clone().unwrap_or_else(|| {
|
||||
paths::sessions_dir().unwrap_or_else(|| PathBuf::from(".insomnia/sessions"))
|
||||
});
|
||||
// Initialize persistent store. `paths::sessions_dir()` only
|
||||
// returns None when none of INSOMNIA_HOME / INSOMNIA_DATA_DIR /
|
||||
// HOME is set — surface that as a hard error to match the
|
||||
// runtime-dir resolution below, rather than silently writing to a
|
||||
// relative path under cwd.
|
||||
let store_dir = match cli.store.clone() {
|
||||
Some(p) => p,
|
||||
None => match paths::sessions_dir() {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
eprintln!(
|
||||
"error: could not resolve sessions directory \
|
||||
(set --store, INSOMNIA_HOME, INSOMNIA_DATA_DIR, or HOME)"
|
||||
);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
},
|
||||
};
|
||||
let store = match FsStore::new(&store_dir).await {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
//!
|
||||
//! Three prefixes address three physical libraries:
|
||||
//!
|
||||
//! | prefix | location |
|
||||
//! |--------------|----------------------------------------------------|
|
||||
//! | `$insomnia` | builtin, baked into the binary via `include_dir!` |
|
||||
//! | `$user` | `$XDG_CONFIG_HOME/insomnia/prompts/` (or similar) |
|
||||
//! | `$workspace` | `<project>/.insomnia/prompts/` |
|
||||
//! | prefix | location |
|
||||
//! |--------------|---------------------------------------------------------|
|
||||
//! | `$insomnia` | builtin, baked into the binary via `include_dir!` |
|
||||
//! | `$user` | `<config_dir>/prompts/` (resolved by `manifest::paths`) |
|
||||
//! | `$workspace` | `<project>/.insomnia/prompts/` |
|
||||
//!
|
||||
//! A reference is `$<prefix>/<path>` where `<path>` is a `/`-separated
|
||||
//! name without the `.md` extension (e.g. `$insomnia/common/header`).
|
||||
|
|
|
|||
|
|
@ -95,7 +95,9 @@ impl RuntimeDir {
|
|||
&self.path
|
||||
}
|
||||
|
||||
/// Path where the Unix socket should be created.
|
||||
/// Path where the Unix socket should be created. External callers
|
||||
/// that only know the pod name (e.g. the TUI's attach flow)
|
||||
/// predict the same path via [`manifest::paths::pod_socket_path`].
|
||||
pub fn socket_path(&self) -> PathBuf {
|
||||
self.path.join("sock")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,14 +87,14 @@ target = "/abs/path"
|
|||
permission = "write"
|
||||
```
|
||||
|
||||
`[model]` は `ref = "<provider>/<model_id>"` でプロバイダ / モデルカタログを引く短縮形と、`scheme` / `model_id` / `auth` を直書きする inline 形式の両方を受ける。カタログは `resources/{providers,models}/builtin.toml` を builtin、`$XDG_CONFIG_HOME/insomnia/{providers,models}.toml` を user override として解決する。詳細は `docs/pod-factory.md` と `crates/provider/README.md`。
|
||||
`[model]` は `ref = "<provider>/<model_id>"` でプロバイダ / モデルカタログを引く短縮形と、`scheme` / `model_id` / `auth` を直書きする inline 形式の両方を受ける。カタログは `resources/{providers,models}/builtin.toml` を builtin、`<config_dir>/{providers,models}.toml` を user override として解決する(`<config_dir>` の解決ルールは `manifest::paths` 参照)。詳細は `docs/pod-factory.md` と `crates/provider/README.md`。
|
||||
|
||||
### PodFactory: カスケード設定
|
||||
|
||||
マニフェストを手書きせず、4 層のカスケードで `PodManifest` を組み立てる:
|
||||
|
||||
1. **ビルトインデフォルト** — `manifest::defaults` の定数値
|
||||
2. **ユーザー manifest** — `$XDG_CONFIG_HOME/insomnia/manifest.toml`
|
||||
2. **ユーザー manifest** — `<config_dir>/manifest.toml`(`manifest::paths` で解決)
|
||||
3. **プロジェクト manifest** — `.insomnia/manifest.toml`(cwd から上方向に探索)
|
||||
4. **プログラマティック overlay** — CLI / GUI / spawn 時のインライン指定
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ permission = "write"
|
|||
`worker.instruction` はファイル参照。3 層の prefix addressing でプロンプト資産を解決:
|
||||
|
||||
- `$insomnia/...` — バイナリ同梱(`resources/prompts/`、`include_dir!` で埋め込み)
|
||||
- `$user/...` — `$XDG_CONFIG_HOME/insomnia/prompts/`
|
||||
- `$user/...` — `<config_dir>/prompts/`(`manifest::paths` で解決)
|
||||
- `$workspace/...` — `<project>/.insomnia/prompts/`
|
||||
|
||||
テンプレートは minijinja で評価。`{% include "$insomnia/common/tool-usage" %}` のようにプロンプト間で参照可能(prefix なしの include は現在のファイルからの相対解決)。
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ Ollama は独自 scheme を作らず `scheme/anthropic` を base_url 差し替
|
|||
## 実装原則
|
||||
|
||||
- 認証ストアを読むアダプタ(`~/.codex/auth.json` 等)は **llm-worker 直下に置かず上位層に配置**。llm-worker は低レベル基盤に留める方針(`feedback_llm_worker_scope.md`)と整合
|
||||
- モデル列挙は **auto_discover と宣言型の両輪**。Ollama は `/api/tags` で自動、OpenAI 互換枠はモデルカタログ(`resources/models/builtin.toml` + `$XDG_CONFIG_HOME/insomnia/models.toml` の user override)で宣言
|
||||
- モデル列挙は **auto_discover と宣言型の両輪**。Ollama は `/api/tags` で自動、OpenAI 互換枠はモデルカタログ(`resources/models/builtin.toml` + `<config_dir>/models.toml` の user override、`<config_dir>` は `manifest::paths` で解決)で宣言
|
||||
- UI のプロバイダ選択肢も第一級 → 二次の優先順位で並べる
|
||||
- **`ollama launch insomnia` 対応を視野に**、env 注入(`ANTHROPIC_BASE_URL` / `OPENAI_BASE_URL` 等)で起動設定を受け入れる作り
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ overlay をマージして、検証済みの `PodManifest` と `PromptLoader`
|
|||
| 優先度 | 層 | 位置 | 典型的な内容 |
|
||||
|---|---|---|---|
|
||||
| 1 | ビルトインのデフォルト | `manifest::defaults` モジュールの `pub const` 群を `PodManifestConfig::builtin_defaults()` が cascade 層として注入 | `tool_output.default_max_bytes = 16KB` など |
|
||||
| 2 | ユーザー manifest | `$XDG_CONFIG_HOME/insomnia/manifest.toml`(未設定時は `~/.config/insomnia/manifest.toml`) | プロバイダ指定、デフォルトモデル、常用ツール設定 |
|
||||
| 2 | ユーザー manifest | `<config_dir>/manifest.toml`(解決ルールは `manifest::paths`) | プロバイダ指定、デフォルトモデル、常用ツール設定 |
|
||||
| 3 | プロジェクト manifest | 起動ディレクトリから上方向に探索した最初の `<root>/.insomnia/manifest.toml` | scope、compaction、プロジェクト固有の instruction |
|
||||
| 4 | プログラマティック overlay | CLI / GUI / 別 Pod からの spawn 等 | `pod.name`、`pod.pwd` のような Pod 固有値 |
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ manifest 中のパス(`provider.api_key_file` / `scope.*.target` /
|
|||
|
||||
| 層 | ベース |
|
||||
|---|---|
|
||||
| user manifest (`~/.config/insomnia/manifest.toml`) | そのファイルの親ディレクトリ |
|
||||
| user manifest (`<config_dir>/manifest.toml`) | そのファイルの親ディレクトリ |
|
||||
| project manifest (`<project>/.insomnia/manifest.toml`) | **プロジェクトルート**(`.insomnia/` の親)。`target = "."` がワークスペース全体を指すように |
|
||||
| overlay(inline TOML・programmatic) | プロセスの `current_dir()` |
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ resolve 段を取りこぼしている証拠なので `ResolveError::RelativePat
|
|||
|
||||
### ユーザー層(最小)
|
||||
|
||||
`$XDG_CONFIG_HOME/insomnia/manifest.toml`:
|
||||
`<config_dir>/manifest.toml`:
|
||||
|
||||
```toml
|
||||
[model]
|
||||
|
|
@ -180,7 +180,7 @@ import-map 形式のプレフィックスで指定する:
|
|||
| プレフィックス | 解決先 |
|
||||
|---|---|
|
||||
| `$insomnia` | バイナリ同梱の `resources/prompts/`(`include_dir!`) |
|
||||
| `$user` | `$XDG_CONFIG_HOME/insomnia/prompts/` |
|
||||
| `$user` | `<config_dir>/prompts/`(`manifest::paths` で解決) |
|
||||
| `$workspace` | `<project>/.insomnia/prompts/` |
|
||||
|
||||
- `.md` 拡張子は省略する(例: `$insomnia/default` → `resources/prompts/default.md`)
|
||||
|
|
@ -238,15 +238,15 @@ pod [--user-manifest <path>] [--project <path>] [--overlay <toml>]
|
|||
|
||||
| フラグ | 説明 |
|
||||
|---|---|
|
||||
| `--user-manifest` | ユーザー manifest のパス。省略時は XDG から自動解決 |
|
||||
| `--user-manifest` | ユーザー manifest のパス。省略時は `manifest::paths::user_manifest_path()` で自動解決 |
|
||||
| `--project` | プロジェクト manifest 探索の起点。省略時は cwd から上方向に `.insomnia/` を探索 |
|
||||
| `--overlay` | 最上層の overlay を inline TOML 文字列で渡す(例: `--overlay 'worker.instruction = "$user/foo"'`) |
|
||||
| `-s, --store` | セッション永続化ディレクトリ(デフォルト: `~/.insomnia/sessions/`) |
|
||||
| `-s, --store` | セッション永続化ディレクトリ(デフォルト: `<data_dir>/sessions/`、`manifest::paths` で解決) |
|
||||
|
||||
Pod の作業ディレクトリは `pod` 起動時の cwd が直接使われる。別ディレクトリで
|
||||
動かしたい場合は `cd <path> && pod ...` のように外側で `cd` してから起動する。
|
||||
|
||||
引数無しで起動すると、cwd + XDG の自動解決だけで動く最小構成になる
|
||||
引数無しで起動すると、cwd + `manifest::paths` の自動解決だけで動く最小構成になる
|
||||
(overlay 無し、プロジェクトに `.insomnia/manifest.toml` があればそれを使う)。
|
||||
|
||||
---
|
||||
|
|
@ -257,7 +257,7 @@ Pod の作業ディレクトリは `pod` 起動時の cwd が直接使われる
|
|||
use pod::{Pod, PodFactory};
|
||||
|
||||
let (manifest, loader) = PodFactory::new()
|
||||
.with_user_manifest_auto()? // XDG から自動読み込み、不在 OK
|
||||
.with_user_manifest_auto()? // manifest::paths から自動読み込み、不在 OK
|
||||
.with_project_manifest_auto()? // cwd から上方向に .insomnia/ を探索、不在 OK
|
||||
.with_overlay_toml(overlay)? // programmatic な最上層 overlay
|
||||
.resolve()?; // -> (PodManifest, PromptLoader)
|
||||
|
|
|
|||
|
|
@ -105,3 +105,9 @@ $XDG_CONFIG_HOME/insomnia/ # 人が編集する設定 (fallback ~/.config/ins
|
|||
## 後続チケット
|
||||
|
||||
- `tickets/tui-user-model-setup.md`: 本チケットで確定したレイアウトに従って user manifest を書き込む wizard を実装する
|
||||
|
||||
## Review
|
||||
|
||||
- 状態: Approve
|
||||
- レビュー詳細: [./home-dir-layout.review.md](./home-dir-layout.review.md)
|
||||
- 日付: 2026-04-27
|
||||
|
|
|
|||
44
tickets/home-dir-layout.review.md
Normal file
44
tickets/home-dir-layout.review.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# 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_<KIND>_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 に分類。
|
||||
Loading…
Reference in New Issue
Block a user