## 🎯 目的 FileBoxをSSOT(Single Source of Truth)設計に移行し、 static/dynamic/builtin providerを統一的に扱える基盤を構築。 ## ✅ 実装完了(7タスク) ### 1. Provider Lock Global **File**: `src/runtime/provider_lock.rs` - `FILEBOX_PROVIDER: OnceLock<Arc<dyn FileIo>>` 追加 - `set_filebox_provider()` / `get_filebox_provider()` 実装 ### 2. VM初期化時のProvider選択 **File**: `src/runner/modes/vm.rs` - `execute_vm_mode()` 冒頭でprovider選択・登録 - ENV(`NYASH_FILEBOX_MODE`, `NYASH_DISABLE_PLUGINS`)対応 ### 3. CoreRoFileIo完全実装 **File**: `src/boxes/file/core_ro.rs` (NEW) - Read-onlyファイルI/O実装 - Thread-safe: `RwLock<Option<File>>` - Newline正規化(CRLF→LF) ### 4. FileBox委譲化 **File**: `src/boxes/file/mod.rs` - 直接`std::fs::File`使用 → `Arc<dyn FileIo>` provider委譲 - 全メソッドをprovider経由に変更 - Fail-Fast: write/delete等の非対応操作は明確エラー ### 5. basic/file_box.rs Deprecate **File**: `src/boxes/file/basic/file_box.rs` - 120行 → 12行に削減 - `#[deprecated]` マーク + 再エクスポート - 後方互換性維持 ### 6. Feature Flag追加 **File**: `Cargo.toml` - `builtin-filebox = []` feature追加 ### 7. Provider抽象・選択ロジック **Files**: - `src/boxes/file/provider.rs` (NEW) - FileIo trait定義 - `src/boxes/file/box_shim.rs` (NEW) - 薄いラッパー - `src/runner/modes/common_util/provider_registry.rs` (NEW) - 選択ロジック ## 📊 アーキテクチャ進化 **Before**: ``` FileBox (mod.rs) ──直接使用──> std::fs::File FileBox (basic/) ──直接使用──> std::fs ``` **After**: ``` FileBox ──委譲──> Arc<dyn FileIo> ──実装──> CoreRoFileIo ├──> PluginFileIo (future) └──> BuiltinFileIo (future) ``` ## 🔧 技術的成果 1. **Thread Safety**: `RwLock<Option<File>>` で並行アクセス安全 2. **Fail-Fast**: 非対応操作は明確エラー(silent failure無し) 3. **後方互換性**: deprecated re-exportで既存コード維持 4. **環境制御**: `NYASH_FILEBOX_MODE` でランタイム切替 ## 📝 環境変数 - `NYASH_FILEBOX_MODE=auto|core-ro|plugin-only` - `auto`: プラグインあれば使用、なければCoreRoにフォールバック - `core-ro`: 強制的にCoreRo(read-only) - `plugin-only`: プラグイン必須(なければFail-Fast) - `NYASH_DISABLE_PLUGINS=1`: 強制的にcore-roモード ## 🎯 次のステップ(Future) - [ ] Dynamic統合(plugin_loaderとの連携) - [ ] BuiltinFileIo実装(feature builtin-filebox) - [ ] Write/Delete等の操作対応(provider拡張) ## 📚 ドキュメント - 詳細仕様: `docs/development/runtime/FILEBOX_PROVIDER.md` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2.7 KiB
2.7 KiB
File I/O Provider Architecture (Core‑RO + Plug‑in)
目的
- File I/O の意味論を単一起源(SSOT)に集約し、コアとプラグインの二重実装・分岐をなくす。
- Analyzer/テスト/CI は FileBox に依存せず動作(--source-file で直接テキストを渡す)。必要時はコアの read‑only 実装で安全に実行。
- 開発/本番はプラグイン(拡張版)を優先し、無い場合はコアにフォールバック。
設計(3層)
- リング0(SSOT / 共有抽象)
src/boxes/file/provider.rstrait FileIo { open(&str), read(), close(), caps(), … }struct FileCaps { read: bool, write: bool }- 共通エラー型・正規化ヘルパ(改行など)
- 役割: File I/O の“意味論”の唯一の真実源。
- リング1(コア最小実装 + 薄いラッパ)
src/boxes/file/core_ro.rs…CoreRoFileIo(read‑only; write は Fail‑Fast)src/boxes/file/box_shim.rs…FileBox { provider: Arc<dyn FileIo> }(委譲のみ; 分岐ロジックなし)
- リング1(選択ポリシー)
src/runner/modes/common_util/provider_registry.rsselect_file_provider(mode: auto|core-ro|plugin-only) -> Arc<dyn FileIo>- 選択はここに閉じ込める(FileBox から分岐を排除)
- リング2(プラグイン実装)
plugins/nyash-filebox-plugin/src/provider.rs…PluginFileIo(write/拡張を実装)- SSOT の
FileIoを実装し、共通意味論に従う
モードと運用
NYASH_FILEBOX_MODE=auto|core-ro|plugin-only- auto(既定): プラグインがあれば PluginFileIo、無ければ CoreRoFileIo
- core-ro: 常に CoreRoFileIo(Analyzer/CI 向け)
- plugin-only: プラグイン必須(無い場合は Fail‑Fast)
NYASH_DISABLE_PLUGINS=1のときは自動で core‑ro を選択- Analyzer/テスト/CI
--source-file <path> <text>を第一経路(FileBox 非依存)- json‑lsp の stdout は純 JSON(ログは stderr)
利点
- File I/O の重複・分岐が provider_registry に一元化され、コードの責務が明確。
- Analyzer/テストはプラグイン非依存で安定(ノイズやロード失敗の影響を受けない)。
- 本番は拡張可能なプラグインを優先しつつ、不在時はコアにフォールバック。
テスト方針
- CoreRo: open/read/close 正常、存在しないパスで Fail‑Fast
- Plugin‑only: write を含む拡張 API 正常(プラグインが無い場合は Fail‑Fast)
- Auto: プラグイン不在時に CoreRo へフォールバック
- Analyzer: 全 HC テストが json‑lsp で緑、stdout は純 JSON を維持