From 2eda4bc86b84ade487a53e1f2e5497b7e29c2755 Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Wed, 3 Dec 2025 19:22:55 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20Phase=20109=20RuntimeProfile=E8=A8=AD?= =?UTF-8?q?=E8=A8=88=E6=8C=87=E7=A4=BA=E6=9B=B8=E8=BF=BD=E5=8A=A0=EF=BC=88?= =?UTF-8?q?=E4=BF=AE=E6=AD=A31-3=E7=B5=B1=E5=90=88=E7=89=88=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 109: minimal/no-fs プロファイル設計の公式指示書を作成。 3つの修正案をすべて統合: 修正1: Task 3「profile読み込み責務分離」 - initialize_runtime()層でのみ env から profile を読む - PluginHost には profile を引数で渡す 修正2: Task 4「Logger関係の明示」 - Ring0.log / ConsoleService は no-fs でも有効 - FileBox のみ disabled 修正3: Task 2「Profile拡張予定」 - RuntimeProfile enum を拡張可能に設計 - 将来 TestMock/Sandbox/ReadOnly/Embedded 対応 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../current/main/phase109_runtime_profiles.md | 424 ++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 docs/development/current/main/phase109_runtime_profiles.md diff --git a/docs/development/current/main/phase109_runtime_profiles.md b/docs/development/current/main/phase109_runtime_profiles.md new file mode 100644 index 00000000..1ff25cfd --- /dev/null +++ b/docs/development/current/main/phase109_runtime_profiles.md @@ -0,0 +1,424 @@ +# Phase 109: minimal/no-fs プロファイル設計(FileBox optional モード) + +## 0. ゴール + +- Phase 107-108 で実装完了した FileBox/Ring0.FsApi パイプラインを、**RuntimeProfile システムで条件付き有効化** する +- selfhost/standard では FileBox が core_required、minimal/no-fs では optional に動的に切り替え可能にする +- **Fail-Fast 原則を維持**:required な場合は初期化時にエラー、optional な場合は黙って無効化 + +--- + +## 1. スコープと非スコープ + +### スコープ(今回やること) + +- RuntimeProfile enum 定義(Default, NoFs)+ phase 108 系 統合 +- CoreBoxId に `is_required_in(profile: &RuntimeProfile) -> bool` ヘルパー追加 +- PluginHost に profile-aware 初期化ロジック追加 +- no-fs profile での FileBox provider チェック(missing OK、Err は "disabled for this profile") +- ドキュメント + テスト追加 + +### 非スコープ(今回はやらない) + +- 実際の TestMock/Sandbox/ReadOnly/Embedded プロファイル実装(Phase 110 以降で検討) +- profile ごとのプラグイン自動フィルタリング(手動制御に) +- Ring0 service registry 統一化(Phase 112 候補) + +--- + +## 2. Task 1: RuntimeProfile enum + is_required_in() ヘルパー + +### 2.1 実装内容 + +**ファイル**: +- `src/runtime/runtime_profile.rs`(新規) +- `src/runtime/core_box_ids.rs`(修正) + +### 2.2 RuntimeProfile 定義 + +```rust +// src/runtime/runtime_profile.rs + +/// Phase 109: RuntimeProfile +/// +/// FileBox(およびその他オプションサービス)の有効/無効を制御する。 +/// +/// - Default: selfhost/standard - ほぼすべてのサービス有効 +/// - NoFs: 最小ランタイム - FileBox/Regex/Time 等をスキップ +/// +/// 拡張予定:TestMock(テスト用), Sandbox(サンドボックス), ReadOnly(読み取り専用), Embedded(組み込み) +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RuntimeProfile { + /// Standard runtime (selfhost/default) + Default, + /// Minimal runtime without FileSystem + NoFs, +} + +impl RuntimeProfile { + /// str から RuntimeProfile を取得 + pub fn from_env() -> Self { + match std::env::var("NYASH_RUNTIME_PROFILE").as_deref() { + Ok("no-fs") | Ok("nofs") => RuntimeProfile::NoFs, + _ => RuntimeProfile::Default, + } + } + + /// デバッグ出力 + pub fn name(&self) -> &'static str { + match self { + RuntimeProfile::Default => "Default", + RuntimeProfile::NoFs => "NoFs", + } + } +} +``` + +### 2.3 CoreBoxId に is_required_in() 追加 + +```rust +// src/runtime/core_box_ids.rs - impl CoreBoxId ブロック内に追加 + +/// Phase 109: profile-aware required チェック +/// +/// - Default: Phase 106 の is_core_required() と同じ(FileBox required) +/// - NoFs: FileBox は optional に(その他 core_required は維持) +pub fn is_required_in(&self, profile: &RuntimeProfile) -> bool { + use CoreBoxId::*; + let core_required = matches!(self, String | Integer | Bool | Array | Map | Console); + + match profile { + RuntimeProfile::Default => { + // Phase 106: File を実質必須扱い + self.is_core_required() + } + RuntimeProfile::NoFs => { + // File 以外は core_required と同じ + core_required + } + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_core_box_id_is_required_in_default() { + let profile = RuntimeProfile::Default; + assert!(CoreBoxId::String.is_required_in(&profile)); + assert!(CoreBoxId::File.is_required_in(&profile)); // Default では required + } + + #[test] + fn test_core_box_id_is_required_in_nofs() { + let profile = RuntimeProfile::NoFs; + assert!(CoreBoxId::String.is_required_in(&profile)); + assert!(!CoreBoxId::File.is_required_in(&profile)); // NoFs では optional + } +} +``` + +### 2.4 Profile 拡張予定(設計メモ) + +```rust +// 将来の enum 拡張予定 +// +// TestMock: テスト用(すべてのプラグインが mock に) +// Sandbox: サンドボックス(外部 I/O 禁止) +// ReadOnly: 読み取り専用(FileBox.write 禁止) +// Embedded: 組み込み(メモリ制限あり、GC あり) +``` + +--- + +## 3. Task 2: PluginHost profile-aware 初期化 + +### 3.1 実装内容 + +**ファイル**: +- `src/runtime/plugin_host.rs`(修正) + +### 3.2 修正内容 + +```rust +// src/runtime/plugin_host.rs + +impl PluginHost { + /// Phase 109: profile-aware with_core_from_registry + pub fn with_core_from_registry( + ring0: Arc, + registry: &UnifiedBoxRegistry, + profile: &RuntimeProfile, // ← 新規引数 + ) -> Result { + // Phase 106: 必須 Box の registered 状態を確認 + for box_id in CoreBoxId::iter() { + if box_id.is_required_in(profile) && !registry.contains(box_id.name()) { + return Err(CoreInitError::MissingService { + box_id, + hint: format!( + "Core Box {} is required in {:?} profile", + box_id.name(), + profile.name() + ), + }); + } + } + + // FileBox provider チェック(Phase 107) + match profile { + RuntimeProfile::Default => { + // Phase 108: FileBox provider 必須 + if provider_lock::get_filebox_provider().is_none() { + return Err(CoreInitError::MissingService { + box_id: CoreBoxId::File, + hint: "FileBox provider not initialized in Default profile".to_string(), + }); + } + } + RuntimeProfile::NoFs => { + // Phase 109: FileBox provider 無くても OK(optional profile) + // provider_lock は無視、下記 Task 3 の disable_filebox() で対応 + } + } + + // ... 以下既存処理 + Ok(self) + } +} + +#[test] +fn test_with_core_from_registry_nofs_filebox_optional() { + // Phase 109: NoFs profile では FileBox provider なしで OK + let ring0 = Arc::new(default_ring0()); + let registry = UnifiedBoxRegistry::with_env_policy(); + let profile = RuntimeProfile::NoFs; + + // provider_lock をクリア(PluginHost が無視するはず) + // → 実装時に適切なクリーンアップロジック追加 + + let result = PluginHost::with_core_from_registry(ring0, ®istry, &profile); + assert!(result.is_ok()); // ✅ 必須でないので OK +} +``` + +--- + +## 4. Task 3: initialize_runtime() に profile 読み込み機構 + +### 4.1 実装内容 + +**ファイル**: +- `src/runner/initialize_runtime.rs`(新規 or 修正) +- `src/runner/modes/vm.rs`(修正) + +### 4.2 修正内容:profile 読み込み層の責務分離 + +**修正1(Task 3 責務明示)**: +```rust +// src/runner/initialize_runtime.rs + +/// Phase 109: profile-aware runtime 初期化 +/// +/// **責務分離**: +/// - initialize_runtime: 環境変数から profile を読む(唯一の env reader) +/// - PluginHost: profile を引数として受け取る(env に依存しない) +pub fn initialize_runtime(ring0: &Arc) -> Result { + // 1. Profile を環境変数から読む(この層のみで実施) + let profile = RuntimeProfile::from_env(); + + // 2. No-FS profile の場合、FileBox provider を明示的に disabled に + if profile == RuntimeProfile::NoFs { + disable_filebox_provider(); + } + + // 3. PluginHost に profile を渡す + let registry = UnifiedBoxRegistry::with_env_policy(); + PluginHost::with_core_from_registry(ring0, ®istry, &profile) +} + +/// Phase 109: no-fs profile 用 FileBox 無効化 +fn disable_filebox_provider() { + // provider_lock に特別な "disabled" マーカーを設定 + // または、Task 4 の ReadOnlyFileIo で Err を返すようにする +} +``` + +--- + +## 5. Task 4: no-fs profile での FileBox 無効化実装 + +### 5.1 実装内容 + +**ファイル**: +- `src/providers/ring1/file/nofs_fileio.rs`(新規) +- `src/runtime/provider_lock.rs`(修正) +- `src/runtime/plugin_host.rs`(修正) + +### 5.2 NoFsFileIo(スタブ実装) + +```rust +// src/providers/ring1/file/nofs_fileio.rs + +/// Phase 109: no-fs profile 用 FileBox stub +/// +/// すべてのメソッドが Err を返す。 +pub struct NoFsFileIo; + +impl FileIo for NoFsFileIo { + fn caps(&self) -> FileCaps { + FileCaps { read: false, write: false } + } + + fn open(&self, path: &str) -> FileResult<()> { + Err(FileError::Unsupported( + "FileBox is disabled in no-fs profile".to_string() + )) + } + + fn read(&self) -> FileResult { + Err(FileError::Unsupported( + "FileBox is disabled in no-fs profile".to_string() + )) + } + + fn write(&self, _text: &str) -> FileResult<()> { + Err(FileError::Unsupported( + "FileBox is disabled in no-fs profile".to_string() + )) + } + + fn close(&self) -> FileResult<()> { + Err(FileError::Unsupported( + "FileBox is disabled in no-fs profile".to_string() + )) + } +} +``` + +### 5.3 provider_lock の profile-aware init + +```rust +// src/runtime/provider_lock.rs + +/// Phase 109: profile を考慮した provider 初期化 +pub fn init_filebox_provider_for_profile( + ring0: &Arc, + profile: &RuntimeProfile, +) -> Result<(), String> { + match profile { + RuntimeProfile::Default => { + // Phase 107: 標準プロファイルでは Ring0FsFileIo を使用 + init_default_filebox_provider(ring0) + } + RuntimeProfile::NoFs => { + // Phase 109: no-fs プロファイルでは NoFsFileIo を使用 + set_filebox_provider(Arc::new(NoFsFileIo)) + } + } +} +``` + +### 5.4 Logger/ConsoleService はそのまま有効(修正2: Logger関係) + +**修正2(Task 4 Logger関係)**: +```rust +// docs/comment + +/// Phase 109: no-fs プロファイルでのサービス有効性 +/// +/// ✅ 有効(no-fs でも必須): +/// - Ring0.log(OS抽象化層 - panic/exit 時の最終出力) +/// - ConsoleBox(言語レベル console - stdout/stderr) +/// - その他 core_required(String/Integer/Array 等) +/// +/// ❌ 無効(no-fs では disabled): +/// - FileBox(ファイルシステム依存) +/// - Regex/Time/JSON等のオプショナル boxes(将来:profile ごとに制御可能) +``` + +--- + +## 6. Task 5: docs 更新 & CURRENT_TASK 反映 + +### 6.1 実装内容 + +**ファイル**: +- `phase108_filebox_write_semantics.md`(追記) +- **新規**: `phase109_runtime_profiles.md`(このドキュメント) +- `core_boxes_design.md`(更新) +- `CURRENT_TASK.md` + +### 6.2 やること + +1. **phase108_filebox_write_semantics.md に追記**: + - Section 9「Phase 109 以降の計画」に: + - 「Phase 109 で RuntimeProfile 機構が追加され、FileBox は conditional required に」 + +2. **phase109_runtime_profiles.md を本ドキュメントとして保存**: + - RuntimeProfile enum + is_required_in() 設計 + - profile 読み込み層の責務分離(修正1) + - Logger/ConsoleService の有効性(修正2) + - 将来 Profile 拡張予定(修正3) + +3. **core_boxes_design.md に追記**: + - Section 5.4「Phase 109 - RuntimeProfile」に: + - 「Default では FileBox required、NoFs では optional」 + - 「profile = env var 読み込み(initialize_runtime 層のみ)」 + - 「将来 TestMock/Sandbox/ReadOnly/Embedded への拡張計画」 + +4. **CURRENT_TASK.md に反映**: + - Phase 109 完了行を追加 + - 次候補(Phase 110 FileHandleBox, Phase 111 append mode)をバックログに記載 + +--- + +## 7. 実装チェックリスト(Phase 109) + +- [ ] RuntimeProfile enum + RuntimeProfile::from_env() 実装 +- [ ] CoreBoxId.is_required_in(profile) ヘルパー実装 +- [ ] NoFsFileIo スタブ実装 +- [ ] PluginHost.with_core_from_registry(profile 引数追加) に profile-aware チェック +- [ ] initialize_runtime に profile 読み込み責務(修正1) +- [ ] initialize_runtime が disable_filebox_provider() 呼び出し(no-fs 時) +- [ ] Logger/ConsoleService の有効性を文書化(修正2) +- [ ] Profile 拡張予定を列挙(修正3) +- [ ] PluginHost.test_with_core_from_registry_nofs_filebox_optional() パス +- [ ] core_boxes_design / phase109 docs / CURRENT_TASK 更新済み +- [ ] ビルド・テスト完全成功 + +--- + +## 8. 設計原則(Phase 109 で確立) + +### RuntimeProfile の位置づけ + +``` +【Layer】 【責務】 【Example】 +──────────────────────────────────────────────────────── +env User configuration NYASH_RUNTIME_PROFILE=no-fs +initialize_runtime() env → RuntimeProfile profile = RuntimeProfile::from_env() +PluginHost profile-aware checks is_required_in(&profile) +CoreBoxId 条件付き required 判定 is_required_in(&profile) +provider_lock provider 登録(Profile 後)set_filebox_provider() +FileBox provider 経由 read/write 実装 +``` + +### Fail-Fast の段階的サポート + +``` +【Profile】 【FileBox チェック】 【Error 時】 +──────────────────────────────────────────────────────── +Default init 時に provider 必須 CoreInitError::MissingService +NoFs init 時に provider OK (optional なので無視) + (実行時 read/write) FileError::Unsupported +``` + +### 拡張ポイント + +- Phase 110: FileHandleBox(複数ファイル同時) +- Phase 111: append mode 追加 +- Phase 112: Ring0 service registry 統一化 +- Phase 113: TestMock/Sandbox/ReadOnly/Embedded profile 実装 + +--- + +**Phase 109 指示書作成日**: 2025-12-03(3修正案統合版)