refactor(tahuantinsuyu): fase 6 — Modules pluggables vía compose + PipelineRequest
El shell ya no carga el flag `show_transits: bool` ni hardcodea qué pipeline corre. La engine expone una sola API `compose(chart, offset, &[PipelineRequest])` que la shell alimenta a partir de un map `module_configs: HashMap<String, serde_json::Value>`. Los toggles de overlay (transit hoy, progression/synastry/solar_arc en fase 7) viven como módulos propios en el panel. - engine: PipelineRequest enum (variante Transit por ahora; comentarios con el roadmap de SecondaryProgression/SolarArc/Synastry). compose() es la nueva entrada canónica; compute / compute_at_offset / compute_with_transits_at_now quedan como atajos retrocompatibles que delegan en compose. bridge.rs refactor: extraído build_transit_overlay como helper que muta &mut RenderModel, listo para que más pipelines apilen capas encima. - modules: nuevo módulo `transit::TransitModule` (id "transit", toggle "enabled" con hotkey [T], applies_to Natal). Sacado el toggle show_transits de NatalModule — ahora cada módulo declara lo suyo. Registry::with_builtins() registra ambos. Test asegura los dos aplican a Natal. - panel: sin cambios — ya itera Registry::for_kind(kind) y renderea cada módulo aplicable con sus controls. La adición del TransitModule aparece automática como segunda card en el panel. - shell: replace show_transits por module_configs map. build_requests() deriva PipelineRequest::Transit cuando module_configs["transit"] ["enabled"] == true. on_panel_event: toggles del NatalModule afectan solo visibility del canvas; toggles de otros módulos van al module_configs y disparan render_current. on_canvas_event: [T] hotkey → flip transit.enabled + sync panel + recompose. apps Cargo agrega serde_json como dep directa. Todos los tests verdes. Fase 7 puede sumar overlays adicionales (progression, solar_arc) solo agregando variantes a PipelineRequest + helpers en bridge + módulos declarativos — sin tocar el shell. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -151,53 +151,60 @@ pub enum EngineError {
|
||||
// API pública
|
||||
// =====================================================================
|
||||
|
||||
/// Computa el RenderModel real contra eternal-astrology si el feature
|
||||
/// está prendido; sino cae al mock.
|
||||
pub fn compute(chart: &Chart) -> Result<RenderModel, EngineError> {
|
||||
compute_at_offset(chart, 0)
|
||||
/// Pedidos que el host (Shell) eleva a la engine para componer un
|
||||
/// `RenderModel`. La capa natal **siempre** se computa; estos requests
|
||||
/// son **overlays adicionales**.
|
||||
///
|
||||
/// Cada variante mapea 1-a-1 con un Module declarado en
|
||||
/// `tahuantinsuyu-modules` por id string. Esto deja la engine como
|
||||
/// dueña única del cómputo (no depende del trait Module — los módulos
|
||||
/// son sólo metadata + UI controls).
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PipelineRequest {
|
||||
/// `module_id = "transit"` — anillo externo con planetas al
|
||||
/// instante actual (reloj de pared) + cross aspects natal × transit.
|
||||
Transit,
|
||||
// ── Fase 7 ──────────────────────────────────────────────────────
|
||||
// SecondaryProgression { target_year: i32 },
|
||||
// SolarArc { target_year: i32 },
|
||||
// Synastry { partner: tahuantinsuyu_model::ChartId },
|
||||
}
|
||||
|
||||
/// Variante con offset temporal en minutos sobre el instante del chart.
|
||||
/// Útil para time-scrubbing: el jog-dial del canvas pasa el offset
|
||||
/// acumulado y la engine recompone toda la pipeline (Asc, casas,
|
||||
/// posiciones planetarias, aspectos) para ese instante desplazado.
|
||||
pub fn compute_at_offset(chart: &Chart, offset_minutes: i64) -> Result<RenderModel, EngineError> {
|
||||
/// Composición canónica: carta natal + todos los overlays pedidos.
|
||||
/// Es la única función que el Shell necesita llamar — `compute_at_offset`
|
||||
/// y `compute_with_transits_at_now` quedan como atajos retrocompatibles.
|
||||
pub fn compose(
|
||||
chart: &Chart,
|
||||
offset_minutes: i64,
|
||||
requests: &[PipelineRequest],
|
||||
) -> Result<RenderModel, EngineError> {
|
||||
#[cfg(feature = "eternal-bridge")]
|
||||
{
|
||||
bridge::compute_at_offset(chart, offset_minutes)
|
||||
bridge::compose(chart, offset_minutes, requests)
|
||||
}
|
||||
#[cfg(not(feature = "eternal-bridge"))]
|
||||
{
|
||||
let _ = offset_minutes;
|
||||
let _ = (offset_minutes, requests);
|
||||
Ok(compute_mock(chart))
|
||||
}
|
||||
}
|
||||
|
||||
/// Variante con overlay de tránsitos al **instante actual** (reloj de
|
||||
/// pared). Computa la carta natal igual que [`compute_at_offset`] y le
|
||||
/// suma dos capas extras:
|
||||
///
|
||||
/// - `LayerKind::Outer` con `module_id = "transit"` — glifos
|
||||
/// planetarios del cielo del momento, sobre un anillo externo.
|
||||
/// - `LayerKind::Aspects` con `module_id = "transit"` — líneas natal ↔
|
||||
/// transit (sólo aspectos mayores). Por convención, en cada
|
||||
/// `LineSeg` el `from_deg` es la longitud natal y el `to_deg` la
|
||||
/// longitud del planeta de tránsito.
|
||||
///
|
||||
/// Sin el feature `eternal-bridge` cae al mock (sin overlay).
|
||||
/// Atajo: natal sin overlays. Equivalente a `compose(chart, 0, &[])`.
|
||||
pub fn compute(chart: &Chart) -> Result<RenderModel, EngineError> {
|
||||
compose(chart, 0, &[])
|
||||
}
|
||||
|
||||
/// Atajo: natal con time-scrubbing pero sin overlays.
|
||||
pub fn compute_at_offset(chart: &Chart, offset_minutes: i64) -> Result<RenderModel, EngineError> {
|
||||
compose(chart, offset_minutes, &[])
|
||||
}
|
||||
|
||||
/// Atajo: natal + overlay de tránsitos al instante actual.
|
||||
pub fn compute_with_transits_at_now(
|
||||
chart: &Chart,
|
||||
offset_minutes: i64,
|
||||
) -> Result<RenderModel, EngineError> {
|
||||
#[cfg(feature = "eternal-bridge")]
|
||||
{
|
||||
bridge::compute_with_transits_at_now(chart, offset_minutes)
|
||||
}
|
||||
#[cfg(not(feature = "eternal-bridge"))]
|
||||
{
|
||||
let _ = offset_minutes;
|
||||
Ok(compute_mock(chart))
|
||||
}
|
||||
compose(chart, offset_minutes, &[PipelineRequest::Transit])
|
||||
}
|
||||
|
||||
/// Stub determinista — útil para tests + para la UI sin eternal.
|
||||
|
||||
Reference in New Issue
Block a user