Phase 21.4 Complete: FileBox SSOT + Analyzer Stabilization (7 Tasks)
✅ Task 1: Fallback Guarantee (create_box failure → ring1/core-ro auto fallback) - Three-tier fallback system: plugin → builtin → core-ro - Mode control: auto/plugin-only/core-ro - New: src/box_factory/builtin_impls/file_box.rs - New: tools/test_filebox_fallback_smoke.sh ✅ Task 2: Provider Registration SSOT (static/dynamic/core-ro unified) - ProviderFactory trait with priority-based selection - Global registry PROVIDER_FACTORIES implementation - Priority: dynamic(100) > builtin(10) > core-ro(0) - New: src/boxes/file/builtin_factory.rs - New: tools/smoke_provider_modes.sh ✅ Task 3: FileBox Publication Unification - Verified: basic/file_box.rs already minimized (11 lines) - Perfect re-export pattern maintained ✅ Task 4: ENV Unification (FILEBOX_MODE/DISABLE_PLUGINS priority) - Removed auto-setting of NYASH_USE_PLUGIN_BUILTINS - Removed auto-setting of NYASH_PLUGIN_OVERRIDE_TYPES - Added deprecation warnings with migration guide - ENV hierarchy: DISABLE_PLUGINS > BOX_FACTORY_POLICY > FILEBOX_MODE ✅ Task 5: Error Log Visibility (Analyzer rule execution errors to stderr) - Added [rule/exec] logging before IR-based rule execution - Format: [rule/exec] HC012 (dead_static_box) <filepath> - VM errors now traceable via stderr output ✅ Task 6: Unnecessary Using Removal (14 rules Str alias cleanup) - Removed unused `using ... as Str` from 14 rule files - All rules use local _itoa() helper instead - 14 lines of dead code eliminated ✅ Task 7: HC017 Skip & TODO Documentation (UTF-8 support required) - Enhanced run_tests.sh with clear skip message - Added "Known Limitations" section to README.md - Technical requirements documented (3 implementation options) - Re-enable timeline: Phase 22 (Unicode Support Phase) 📊 Test Results: - Analyzer: 10 tests PASS, 1 skipped (HC017) - FileBox fallback: All 3 modes PASS - Provider modes: All 4 modes PASS - Build: Success (0 errors, 0 warnings) 🎯 Key Achievements: - 28 files modified/created - Three-Tier Fallback System (stability) - SSOT Provider Registry (extensibility) - ENV unification (operational clarity) - Error visibility (debugging efficiency) - Code cleanup (maintainability) - Comprehensive documentation (Phase 22 ready) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -1,16 +1,34 @@
|
||||
//! Provider registry: selects concrete providers for core resources (e.g. FileBox).
|
||||
//! This is a placeholder documenting the intended API; wiring is added later.
|
||||
//! SSOT (Single Source of Truth) for provider selection via ProviderFactory registration.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex, OnceLock};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::boxes::file::provider::FileIo;
|
||||
#[allow(unused_imports)]
|
||||
use crate::boxes::file::core_ro::CoreRoFileIo;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum FileBoxMode { Auto, CoreRo, PluginOnly }
|
||||
|
||||
/// Factory for creating FileIo providers
|
||||
pub trait ProviderFactory: Send + Sync {
|
||||
fn box_name(&self) -> &str;
|
||||
fn create_provider(&self) -> Arc<dyn FileIo>;
|
||||
fn is_available(&self) -> bool;
|
||||
fn priority(&self) -> i32 {
|
||||
0 // Default priority (higher = preferred)
|
||||
}
|
||||
}
|
||||
|
||||
/// Global registry of provider factories
|
||||
static PROVIDER_FACTORIES: OnceLock<Mutex<Vec<Arc<dyn ProviderFactory>>>> = OnceLock::new();
|
||||
|
||||
/// Register a provider factory (called by builtin/dynamic loaders)
|
||||
pub fn register_provider_factory(factory: Arc<dyn ProviderFactory>) {
|
||||
let registry = PROVIDER_FACTORIES.get_or_init(|| Mutex::new(Vec::new()));
|
||||
registry.lock().unwrap().push(factory);
|
||||
}
|
||||
|
||||
/// Read FileBox mode from environment variables
|
||||
#[allow(dead_code)]
|
||||
pub fn read_filebox_mode_from_env() -> FileBoxMode {
|
||||
match std::env::var("NYASH_FILEBOX_MODE").unwrap_or_else(|_| "auto".to_string()).as_str() {
|
||||
@ -24,12 +42,65 @@ pub fn read_filebox_mode_from_env() -> FileBoxMode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Select provider based on mode and registered factories (SSOT)
|
||||
#[allow(dead_code)]
|
||||
pub fn select_file_provider(mode: FileBoxMode) -> Arc<dyn FileIo> {
|
||||
let registry = PROVIDER_FACTORIES.get();
|
||||
let quiet_pipe = crate::config::env::env_bool("NYASH_JSON_ONLY");
|
||||
|
||||
match mode {
|
||||
FileBoxMode::CoreRo => Arc::new(CoreRoFileIo::new()),
|
||||
FileBoxMode::PluginOnly | FileBoxMode::Auto => {
|
||||
// TODO: if plugin present, return PluginFileIo; otherwise fallback/Fail-Fast
|
||||
FileBoxMode::Auto => {
|
||||
// Try: dynamic/builtin (by priority) → core-ro fallback
|
||||
if let Some(reg) = registry {
|
||||
let mut factories: Vec<_> = reg.lock().unwrap()
|
||||
.iter()
|
||||
.filter(|f| f.box_name() == "FileBox" && f.is_available())
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
// Sort by priority (descending)
|
||||
factories.sort_by(|a, b| b.priority().cmp(&a.priority()));
|
||||
|
||||
if let Some(factory) = factories.first() {
|
||||
if !quiet_pipe {
|
||||
eprintln!("[provider-registry] FileBox: using registered provider (priority={})", factory.priority());
|
||||
}
|
||||
return factory.create_provider();
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to core-ro
|
||||
if !quiet_pipe {
|
||||
eprintln!("[provider-registry] FileBox: using core-ro fallback");
|
||||
}
|
||||
Arc::new(CoreRoFileIo::new())
|
||||
}
|
||||
FileBoxMode::PluginOnly => {
|
||||
// Try only registered providers, Fail-Fast if none available
|
||||
if let Some(reg) = registry {
|
||||
let mut factories: Vec<_> = reg.lock().unwrap()
|
||||
.iter()
|
||||
.filter(|f| f.box_name() == "FileBox" && f.is_available())
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
factories.sort_by(|a, b| b.priority().cmp(&a.priority()));
|
||||
|
||||
if let Some(factory) = factories.first() {
|
||||
if !quiet_pipe {
|
||||
eprintln!("[provider-registry] FileBox: using plugin-only provider (priority={})", factory.priority());
|
||||
}
|
||||
return factory.create_provider();
|
||||
}
|
||||
}
|
||||
|
||||
panic!("FileBox plugin-only mode: no provider registered. Set NYASH_FILEBOX_MODE=auto or NYASH_FILEBOX_MODE=core-ro to use fallback.");
|
||||
}
|
||||
FileBoxMode::CoreRo => {
|
||||
// Always use core-ro, ignore registry
|
||||
if !quiet_pipe {
|
||||
eprintln!("[provider-registry] FileBox: using core-ro (forced)");
|
||||
}
|
||||
Arc::new(CoreRoFileIo::new())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user