mirbuilder: integrate Normalizer (toggle), add tag-quiet mode, share f64 canonicalization; expand canaries; doc updates for quick timeout + dev toggles; Phase 21.5 optimization readiness

This commit is contained in:
nyash-codex
2025-11-10 23:17:46 +09:00
parent 24d88a10c0
commit ece91306b7
56 changed files with 2227 additions and 142 deletions

View File

@ -6,6 +6,17 @@ use std::sync::{Arc, Mutex, OnceLock};
use crate::boxes::file::provider::FileIo;
use crate::boxes::file::core_ro::CoreRoFileIo;
/// Provider selection policy (global). Applied when mode=Auto.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum ProviderPolicy {
/// Current default: prefer plugin/dynamic providers by priority; use ring-1 as fallback
StrictPluginFirst,
/// Prefer ring-1 (static/core-ro) for stability/CI; fall back to plugin if unavailable
SafeCoreFirst,
/// Alias to SafeCoreFirst for future extension
StaticPreferred,
}
#[allow(dead_code)]
pub enum FileBoxMode { Auto, CoreRo, PluginOnly }
@ -49,6 +60,15 @@ fn ensure_builtin_file_provider_registered() {
}
}
/// Read global provider policy (affects Auto mode only)
fn read_provider_policy_from_env() -> ProviderPolicy {
match std::env::var("HAKO_PROVIDER_POLICY").unwrap_or_else(|_| "strict-plugin-first".to_string()).as_str() {
"safe-core-first" => ProviderPolicy::SafeCoreFirst,
"static-preferred" => ProviderPolicy::StaticPreferred,
_ => ProviderPolicy::StrictPluginFirst,
}
}
/// Read FileBox mode from environment variables
#[allow(dead_code)]
pub fn read_filebox_mode_from_env() -> FileBoxMode {
@ -73,7 +93,8 @@ pub fn select_file_provider(mode: FileBoxMode) -> Arc<dyn FileIo> {
match mode {
FileBoxMode::Auto => {
// Try: dynamic/builtin (by priority) → core-ro fallback
// Selection by global policy
let policy = read_provider_policy_from_env();
if let Some(reg) = registry {
let mut factories: Vec<_> = reg.lock().unwrap()
.iter()
@ -81,14 +102,38 @@ pub fn select_file_provider(mode: FileBoxMode) -> Arc<dyn FileIo> {
.cloned()
.collect();
// Sort by priority (descending)
// Sort by priority (descending); plugin providers should rank higher than ring-1 (priority -100)
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());
// Try policy-driven choice first
match policy {
ProviderPolicy::StrictPluginFirst => {
if let Some(factory) = factories.first() {
if !quiet_pipe || std::env::var("HAKO_PROVIDER_TRACE").as_deref() == Ok("1") {
eprintln!("[provider-registry] FileBox: using registered provider (priority={})", factory.priority());
eprintln!("[provider/select:FileBox ring=plugin src=dynamic]");
}
return factory.create_provider();
}
}
ProviderPolicy::SafeCoreFirst | ProviderPolicy::StaticPreferred => {
// Prefer ring-1 (priority <= -100)
if let Some(core_ro) = factories.iter().find(|f| f.priority() <= -100) {
if !quiet_pipe || std::env::var("HAKO_PROVIDER_TRACE").as_deref() == Ok("1") {
eprintln!("[provider-registry] FileBox: using core-ro (policy)");
eprintln!("[provider/select:FileBox ring=1 src=static caps=[read]]");
}
return core_ro.create_provider();
}
// Fallback to first available (plugin)
if let Some(factory) = factories.first() {
if !quiet_pipe || std::env::var("HAKO_PROVIDER_TRACE").as_deref() == Ok("1") {
eprintln!("[provider-registry] FileBox: using registered provider (priority={})", factory.priority());
eprintln!("[provider/select:FileBox ring=plugin src=dynamic]");
}
return factory.create_provider();
}
}
return factory.create_provider();
}
}
@ -105,11 +150,12 @@ pub fn select_file_provider(mode: FileBoxMode) -> Arc<dyn FileIo> {
eprintln!("[failfast/provider/filebox:auto-fallback-blocked]");
panic!("Fail-Fast: FileBox provider fallback is disabled (NYASH_FAIL_FAST=0 or NYASH_FILEBOX_ALLOW_FALLBACK=1 to override)");
} else {
if !quiet_pipe {
if !quiet_pipe || std::env::var("HAKO_PROVIDER_TRACE").as_deref() == Ok("1") {
eprintln!(
"[provider-registry] FileBox: using core-ro fallback{}",
if allow_fb_override { " (override)" } else { "" }
);
eprintln!("[provider/select:FileBox ring=1 src=static caps=[read]]");
}
Arc::new(CoreRoFileIo::new())
}
@ -126,8 +172,9 @@ pub fn select_file_provider(mode: FileBoxMode) -> Arc<dyn FileIo> {
factories.sort_by(|a, b| b.priority().cmp(&a.priority()));
if let Some(factory) = factories.first() {
if !quiet_pipe {
if !quiet_pipe || std::env::var("HAKO_PROVIDER_TRACE").as_deref() == Ok("1") {
eprintln!("[provider-registry] FileBox: using plugin-only provider (priority={})", factory.priority());
eprintln!("[provider/select:FileBox ring=plugin src=dynamic]");
}
return factory.create_provider();
}
@ -137,10 +184,21 @@ pub fn select_file_provider(mode: FileBoxMode) -> Arc<dyn FileIo> {
}
FileBoxMode::CoreRo => {
// Always use core-ro, ignore registry
if !quiet_pipe {
if !quiet_pipe || std::env::var("HAKO_PROVIDER_TRACE").as_deref() == Ok("1") {
eprintln!("[provider-registry] FileBox: using core-ro (forced)");
eprintln!("[provider/select:FileBox ring=1 src=static caps=[read]]");
}
Arc::new(CoreRoFileIo::new())
}
}
}
/// Provider descriptor (ring/source/capabilities). Currently informational.
#[allow(dead_code)]
#[derive(Clone, Debug)]
struct ProviderDescriptor {
box_name: &'static str,
ring: &'static str, // "0" | "1" | "plugin"
source: &'static str, // "static" | "dynamic"
capabilities: &'static [&'static str], // e.g., ["read"]
priority: i32,
}