evorule-reactor 0.2.1

Reactive fact-driven state transition engine with audit chain, time machine, and WAL
Documentation

evorule-reactor

EvoRule 三层架构的 Tier 1 反应式执行器 —— 事实驱动的状态转换引擎。

  • 版本:v0.2.1
  • 依赖:evorule-tcb = "0.2.1"
  • 协议:AGPL-3.0-or-later
  • 测试:cargo test 全部 PASS(含 complex_rule_test / reactor_test / ffi_test 等)
  • build.rs 编译时门禁:F11 禁止 unwrap/expect/panic!/debug_assert!(非测试代码),G8 控制流白盒化,PASSED
  • G8 门控遵守:反应器主循环(reactor.rs)的控制流分支是策略数据(Fact 变体的 match)而非硬编码业务逻辑;任何业务分支均由 core_eval.json 数据驱动,编译期通过 build.rs 递归扫描确认。
  • unsafe:#![forbid(unsafe_code)](ffi.rs 局部豁免 #![allow(unsafe_code)],FFI 边界,已文档化)
  • P0 修复(2026-07-25):Box::leak 内存泄漏已修复(IoType::parse 返回 Option);锁中毒改为 e.into_inner() 恢复(非 panic)
  • v0.2.0 重构(2026-08-04):IoType 内部从 &'static str 改为 Arc<str>,支持 IoType::new() 注册任意 io_type(失去 Copy,5 个 const 改工厂函数);IoHandler/IoDispatcher 从 governance 下沉至本 crate(trait 改 #[async_trait] object-safe);IoType::parse 标记 #[deprecated]。详见 MIGRATION_v0.2.0.md

设计原则

  • 事实驱动:所有交互通过 Fact 通道进行
  • 单一串行通道:保证调度确定性
  • 稳定检测:队列空 + 无待处理 I/O = 稳定
  • 无状态泄漏:所有状态由反应器维护
  • Append-Only 审计链:所有 Fact 追加到 FactsLog,支持审计重放
  • 哈希链完整性:每个 Fact 写入 WAL 时自动计算 BLAKE3 哈希链(content_hash/prev_hash/chain_hash),篡改可检测

架构

用户/治理层 → FactSender → [command mpsc] → 反应器
                                              ↓
                                        调用 TCB 核心
                                              ↓
                              产生新 Fact → event broadcast → 用户/I/O 订阅者/审计器
                                              ↓
                              所有 Fact → FactsLog(审计链 + 哈希链)

模块结构

src/
├── channel.rs          # 通道封装(command/event)
├── error.rs            # 错误类型(ReactorError / FactsLogError 等)
├── fact.rs             # Fact 枚举(7 种变体)+ FactId + IoType
├── facts_log.rs        # Append-Only FactsLog(内存 + WAL 持久化 + 哈希链)
├── ffi.rs              # C FFI 接口(feature = "ffi")
├── hash.rs             # BLAKE3 哈希链算法(单一真相源,tier2/CLI re-export)
├── invariants.rs       # 结构不变量检查
├── io_dispatcher.rs    # I/O 分发器(v0.2.0 从 governance 下沉;builder + register(IoType, handler))
├── io_handler.rs       # IoHandler trait + IoResult(v0.2.0 从 governance 下沉;#[async_trait] object-safe)
├── lib.rs              # 模块声明 + 公共 API 导出
├── phase.rs            # 反应器阶段(Executing/Idle/Stable 等)
├── pure.rs             # 纯函数执行器(TCB 调用封装)
├── reactor.rs          # 反应器主循环 + ReactorBuilder + ReactorHandle
├── stable_detector.rs  # 稳定状态检测器
├── state.rs            # 反应器状态快照
└── wal.rs              # WAL 读写(JSONL 格式,含哈希字段)

快速入门

use evorule_reactor::{Reactor, Fact, FactId};
use evorule_tcb::JsonValue;

let core_eval = vec![];
let reactor = Reactor::builder(core_eval).max_rounds(1000).build();
let (tx, mut rx, _event_tx, _handle, _facts_log) = reactor.spawn();

tx.send(Fact::Command {
    id: FactId(1),
    instruction: JsonValue::object_from_pairs(&[
        ("type", JsonValue::string("increment")),
        ("params", JsonValue::object_from_pairs(&[
            ("attr", JsonValue::string("x")),
            ("delta", JsonValue::Integer(5)),
        ])),
    ]),
}).unwrap();

while let Ok(fact) = rx.recv().await {
    if let Fact::Stable { final_snapshot, .. } = fact {
        println!("完成: {:?}", final_snapshot);
        break;
    }
}

API 列表

Reactor

方法 说明
Reactor::builder(core_eval) 创建反应器构建器
builder.max_rounds(n) 设置最大执行轮数
builder.build() 构建反应器实例
reactor.spawn() 启动反应器,返回通道和句柄

ReactorHandle

方法 说明
handle.join() 等待反应器完成
handle.abort() 中止反应器
handle.is_finished() 查询反应器是否已结束
handle.current_phase() 获取当前阶段
handle.causal_depth() 获取因果深度
handle.structural_invariant_violations() 获取结构不变量违规计数
handle.pending_io_count() 获取待处理 I/O 数量
handle.current_step() 获取当前执行步数
handle.snapshot() 获取反应器状态快照
handle.interrupt() 中断执行

Fact 类型

类型 说明
Fact::Command 用户命令(触发执行)
Fact::StateTransition 状态转换(反应器自动产生,携带 cause 因果链)
Fact::Stable 稳定状态(队列空 + 无 pending I/O)
Fact::Error 错误(超时 / TCB 错误 / 队列溢出)
Fact::IoRequest I/O 请求(TCB 产生,治理层消费)
Fact::IoResponse I/O 响应(治理层产生,反应器消费)
Fact::PayloadUpdate 负载更新(治理层注入)

审计链与哈希链

WAL 格式(含哈希链)

每条 WAL 记录包含以下字段:

{
  "version_before": 0,
  "fact": {"type": "Command", "id": 1, "instruction": {...}},
  "content_hash": "blake3(fact_to_stable_json(fact))",
  "prev_hash": "前一条的 chain_hash(首条为 \"genesis\"",
  "chain_hash": "blake3(prev_hash + content_hash)"
}

哈希链算法

  • 单一真相源evorule_reactor::hash 模块
  • 算法:BLAKE3
  • content_hash = blake3(fact_to_stable_json(fact))
  • chain_hash = blake3(prev_hash + content_hash)
  • 初始 prev_hash = "genesis"
  • evorule-governance 和 evorule-cli 通过 re-export 使用同一算法,三方哈希值字节级一致

FactsLog

方法 说明
FactsLog::new() 创建纯内存 FactsLog
FactsLog::with_wal(path) 创建带 WAL 持久化的 FactsLog
FactsLog::recover(path) 从 WAL 恢复 FactsLog(重放 + 挂载)
facts_log.append(fact) 追加 Fact(自动计算哈希链 + 写 WAL)
facts_log.last_hash() 获取审计链末尾哈希
facts_log.history() 获取全部 Fact 历史
facts_log.version() 获取当前版本号

C FFI 接口

启用 ffi feature 编译动态链接库:

cargo build --features ffi --release

C API 示例

#include "include/evorule.h"

evorule_reactor* reactor = evorule_reactor_new();
evorule_reactor_send_command(reactor, "{\"type\": \"increment\"}");
evorule_reactor_free(reactor);

Feature Flags

Feature 说明
persistence WAL 持久化(FactsLog + 哈希链写入磁盘)
ffi C FFI 接口(生成 cdylib)
kani Kani 形式化验证(保留标记)

版本策略

本项目遵循 Semantic Versioning

  • MAJOR:API 不兼容变更
  • MINOR:向后兼容的功能新增
  • PATCH:向后兼容的 bug 修复

设计文档参考


许可证

代码:AGPL-3.0-or-later(见 LICENSE 文件)。