feat(phase92): UnifiedBoxRegistry integration roadmap complete

Phase 92 完了: UnifiedBoxRegistry 統合の導線作り

**実装内容**:
- CoreServices::required_ids() 実装
  - Phase 87 CoreBoxId の core_required (6個) を返す
  - is_core_required() との整合性を型レベルで保証
- CoreInitError enum 追加
  - MissingService, RegistryEmpty, InvalidServiceType
  - Display + std::error::Error trait 実装
- PluginHost::with_core_from_registry() skeleton
  - Phase 93 で実装予定(todo!() でプレースホルダー)
- initialize_runtime() 接続ポイント決定
  - Ring0Context と UnifiedBoxRegistry を橋渡し

**Phase 87 整合性**:
- required_ids() が is_core_required() と完全一致
- テストで整合性を検証

**テスト結果**:
- 3件追加(全て合格)
  - test_required_ids_consistency
  - test_core_init_error_display
  - test_with_core_from_registry_todo (should_panic)
- ビルド成功
- 既存テストに影響なし

**ドキュメント更新**:
- Section 9 追加(113行)
- ensure_initialized() 呼び出し場所決定(4箇所)
- Phase 93 実装計画明記

**次のステップ**: Phase 93 (with_core_from_registry 実装 & 起動パス統合)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-03 07:57:21 +09:00
parent 3d253056bd
commit 2f54e64d27
4 changed files with 233 additions and 0 deletions

View File

@ -363,3 +363,107 @@ pub trait NyashPlugin: Send + Sync {
- PluginHost.optional への optional/user プラグイン登録
- 既存 Box 実装と Service trait の接続
---
## 9. Phase 92: UnifiedBoxRegistry 統合計画2025-12-03
### 9.1 CoreServices と CoreBoxId の対応テーブル
**実装**: `src/runtime/core_services.rs`
```rust
impl CoreServices {
pub fn required_ids() -> &'static [CoreBoxId] {
&[
CoreBoxId::String,
CoreBoxId::Integer,
CoreBoxId::Bool,
CoreBoxId::Array,
CoreBoxId::Map,
CoreBoxId::Console,
]
}
}
```
**Phase 87 整合性**: CoreBoxId::is_core_required() と完全一致
### 9.2 PluginHost 初期化フック
**実装**: `src/runtime/plugin_host.rs`
```rust
impl PluginHost {
pub fn with_core_from_registry(
ring0: Arc<Ring0Context>,
registry: &UnifiedBoxRegistry,
) -> Result<Self, CoreInitError> {
// Phase 93 で実装予定
todo!("Phase 93: UnifiedBoxRegistry から CoreServices への変換実装")
}
}
```
**エラー型**: `CoreInitError` で不足している core service を明示
### 9.3 Runtime 初期化接続ポイント
**実装**: `src/runtime/mod.rs`
```rust
pub fn initialize_runtime(ring0: Arc<Ring0Context>) -> Result<PluginHost, CoreInitError> {
let registry = UnifiedBoxRegistry::new();
let plugin_host = PluginHost::with_core_from_registry(ring0, &registry)?;
Ok(plugin_host)
}
```
**Phase 93 で実装**: UnifiedBoxRegistry から CoreServices への実際の変換
### 9.4 ensure_initialized() 呼び出し場所Phase 93 実装予定)
**決定事項**: Phase 93 以降で以下の4箇所で呼び出す
1. **selfhost ランナー起動時**`src/runner/selfhost.rs`
```rust
pub fn run_selfhost(config: &Config) -> Result<(), Error> {
let plugin_host = initialize_runtime(get_global_ring0())?;
plugin_host.ensure_core_initialized();
// ...
}
```
2. **hack_check 実行前**`src/runner/hack_check.rs`
```rust
pub fn run_hack_check() -> Result<(), Error> {
let plugin_host = initialize_runtime(get_global_ring0())?;
plugin_host.ensure_core_initialized();
// ...
}
```
3. **VM バックエンド起動時**`src/runner/modes/vm.rs`
```rust
pub fn run_vm(program: &str) -> Result<(), Error> {
let plugin_host = initialize_runtime(get_global_ring0())?;
plugin_host.ensure_core_initialized();
// ...
}
```
4. **統合テスト setup**`tests/integration/setup.rs`
```rust
pub fn setup_test_runtime() -> PluginHost {
let plugin_host = initialize_runtime(get_global_ring0()).unwrap();
plugin_host.ensure_core_initialized();
plugin_host
}
```
### 9.5 Phase 93 実装計画
- UnifiedBoxRegistry から core_required Box の取得
- Box → Service trait への変換ロジック
- CoreServices の自動構築
- ensure_initialized() の4箇所への配置

View File

@ -4,6 +4,7 @@
//! Phase 87 CoreBoxId の core_required (6個) 全てをカバー。
use std::sync::Arc;
use crate::runtime::CoreBoxId;
/// StringBox Service trait
pub trait StringService: Send + Sync {
@ -58,6 +59,20 @@ pub struct CoreServices {
}
impl CoreServices {
/// Phase 87 CoreBoxId の core_required (6個) を返す
///
/// Phase 87 CoreBoxId::is_core_required() と完全一致する。
pub fn required_ids() -> &'static [CoreBoxId] {
&[
CoreBoxId::String,
CoreBoxId::Integer,
CoreBoxId::Bool,
CoreBoxId::Array,
CoreBoxId::Map,
CoreBoxId::Console,
]
}
/// 全フィールドが初期化されているか検証
/// Phase 92 以降で各 Service の初期化を検証
pub fn ensure_initialized(&self) {
@ -65,3 +80,27 @@ impl CoreServices {
// Phase 92 以降で各 Service の初期化を検証
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_required_ids_consistency() {
let required = CoreServices::required_ids();
assert_eq!(required.len(), 6);
// Phase 87 CoreBoxId::is_core_required() と一致
for id in required {
assert!(id.is_core_required());
}
// 全ての core_required が含まれているか確認
assert!(required.contains(&CoreBoxId::String));
assert!(required.contains(&CoreBoxId::Integer));
assert!(required.contains(&CoreBoxId::Bool));
assert!(required.contains(&CoreBoxId::Array));
assert!(required.contains(&CoreBoxId::Map));
assert!(required.contains(&CoreBoxId::Console));
}
}

View File

@ -42,6 +42,7 @@ pub use box_registry::{get_global_registry, BoxFactoryRegistry, BoxProvider};
pub use core_box_ids::{CoreBoxCategory, CoreBoxId, CoreMethodId}; // Phase 87: 型安全enum
pub use plugin_config::PluginConfig;
pub use ring0::{get_global_ring0, init_global_ring0, Ring0Context}; // Phase 88: Ring0 公開 API
pub use plugin_host::CoreInitError; // Phase 92: CoreServices 初期化エラー
pub use plugin_loader_unified::{
get_global_plugin_host, init_global_plugin_host, MethodHandle, PluginBoxType, PluginHost,
PluginLibraryHandle,
@ -57,3 +58,19 @@ pub use unified_registry::{
// pub use plugin_box::PluginBox; // legacy
// Use unified plugin loader (formerly v2)
// pub use plugin_loader::{PluginLoaderV2 as PluginLoader, get_global_loader_v2 as get_global_loader}; // legacy
/// Runtime 初期化Phase 92: 接続ポイント決定)
///
/// Phase 93 で実装予定の接続ポイント。
/// Phase 92 では skeleton のみtodo!() を呼ぶ)。
#[allow(dead_code)]
pub fn initialize_runtime(ring0: std::sync::Arc<Ring0Context>) -> Result<plugin_host::PluginHost, CoreInitError> {
use crate::box_factory::UnifiedBoxRegistry;
let registry = UnifiedBoxRegistry::new();
// Phase 92: 接続ポイント決定(実装は Phase 93
let plugin_host = plugin_host::PluginHost::with_core_from_registry(ring0, &registry)?;
Ok(plugin_host)
}

View File

@ -6,6 +6,8 @@
use std::sync::Arc;
use std::collections::HashMap;
use std::any::Any;
use crate::box_factory::UnifiedBoxRegistry;
use crate::runtime::CoreBoxId;
/// Plugin の基本情報
#[derive(Debug, Clone)]
@ -37,6 +39,39 @@ impl PluginRegistry {
use super::core_services::CoreServices;
use super::ring0::Ring0Context;
/// CoreServices 初期化エラー
#[derive(Debug, Clone)]
pub enum CoreInitError {
MissingService {
box_id: CoreBoxId,
message: String,
},
RegistryEmpty,
InvalidServiceType {
box_id: CoreBoxId,
expected: &'static str,
found: String,
},
}
impl std::fmt::Display for CoreInitError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
CoreInitError::MissingService { box_id, message } => {
write!(f, "Missing core service {:?}: {}", box_id, message)
}
CoreInitError::RegistryEmpty => {
write!(f, "UnifiedBoxRegistry is empty")
}
CoreInitError::InvalidServiceType { box_id, expected, found } => {
write!(f, "Invalid service type for {:?}: expected {}, found {}", box_id, expected, found)
}
}
}
}
impl std::error::Error for CoreInitError {}
/// PluginHost: Ring0Context と CoreServices の橋渡し
pub struct PluginHost {
pub ring0: Arc<Ring0Context>,
@ -53,6 +88,21 @@ impl PluginHost {
unimplemented!("Phase 92 で from_registry() 実装後に削除")
}
/// UnifiedBoxRegistry から core_required Box を取得して CoreServices を初期化
///
/// Phase 92: skeleton のみPhase 93 で実装)
#[allow(dead_code)]
pub fn with_core_from_registry(
ring0: Arc<Ring0Context>,
_registry: &UnifiedBoxRegistry,
) -> Result<Self, CoreInitError> {
// Phase 93 で実装予定
// TODO: registry から core_required Box を取得
// TODO: 各 Box を対応する Service trait に変換
// TODO: CoreServices を構築
todo!("Phase 93: UnifiedBoxRegistry から CoreServices への変換実装")
}
/// core_required が全て揃っているか検証
pub fn ensure_core_initialized(&self) {
self.core.ensure_initialized();
@ -160,4 +210,27 @@ mod tests {
assert_eq!(desc.name, "dummy");
assert_eq!(desc.version, "0.1.0");
}
#[test]
fn test_core_init_error_display() {
let error = CoreInitError::MissingService {
box_id: CoreBoxId::String,
message: "StringBox not found".to_string(),
};
let display = format!("{}", error);
assert!(display.contains("String"));
assert!(display.contains("not found"));
}
#[test]
#[should_panic(expected = "Phase 93")]
fn test_with_core_from_registry_todo() {
// Phase 92: todo!() を返すことを確認
use crate::runtime::ring0::default_ring0;
let ring0 = Arc::new(default_ring0());
let registry = UnifiedBoxRegistry::new();
let _result = PluginHost::with_core_from_registry(ring0, &registry);
// Phase 93 で実装後はこのテストを削除
}
}