跳转至

DiPECS v0.2 — 端到端处理管道打通

日期: 2026-05-05 基线: v0.1 (aios-spec 宪法层 + aios-core 核心逻辑 + collector 采集骨架) 主题: 从单纯采集升级为完整的「采集 → 脱敏 → 聚合 → 模拟推理 → 校验 → 执行」管道


一、架构变更总览

v0.1 的 daemon 只有一条采集循环,sanitizer / policy / executor 存在但未被调用。v0.2 将它们全部串入管道。

v0.1:  [采集线程] → bus.push() → (丢进虚空)

v0.2:  ┌─ Task 1 (采集) ────────────────────────┐
        │  ProcReader / BinderProbe / SysCollector│
        │         │ raw_events_tx (mpsc)          │
        └─────────┼───────────────────────────────┘
        ┌─────────▼───────────────────────────────┐
        │  Task 2 (处理管道)                       │
        │                                         │
        │  raw_events_rx → PrivacyAirGap.sanitize │
        │                → WindowAggregator (10s)  │
        │                → MockCloudProxy          │
        │                → PolicyEngine.evaluate   │
        │                → ActionExecutor.execute  │
        └─────────────────────────────────────────┘

二、新增模块

2.1 aios-agent — Mock CloudProxy (crates/aios-agent/)

新增文件: src/lib.rs (207 行)

首次实现 agent 层。当前阶段为 Mock,后续替换为真实 HTTPS 通信 (reqwest + rustls)。

API

pub struct MockCloudProxy;

impl MockCloudProxy {
    pub fn evaluate(context: &StructuredContext) -> IntentBatch;
}

模拟决策规则

检测信号 生成意图 推荐动作 置信度
通知含 FileMention OpenApp(source_app) PreWarmProcess 0.70
ActivityLaunch 检测 SwitchToApp(target) PreWarmProcess + KeepAlive 0.85
文件活动 (任意) HandleFile(ext_category) PrefetchFile 0.75
屏幕亮起 Idle KeepAlive(foreground) 0.60
电量 < 20% Idle ReleaseMemory 0.80
空窗口 Idle NoOp 0.50

方法细节

evaluate(context: &StructuredContext) -> IntentBatch (crates/aios-agent/src/lib.rs:35)

接收一个 10s 时间窗口的结构化上下文,返回模拟的 IntentBatch。内部调用 generate_intents() 进行信号匹配和意图生成。所有意图的风险等级与模型标识 (mock-cloud-proxy-v0.1) 为固定值,方便在日志中区分 mock 与真实云端返回。

generate_intents(context: &StructuredContext) -> Vec<Intent> (crates/aios-agent/src/lib.rs:43)

遍历窗口内的 SanitizedEvent 序列,累计六大信号位 (has_file_mention, has_activity_launch, launched_apps, has_screen_on, is_low_battery, notified_apps)。文件活动事件(FileActivity)直接为每个扩展名类别生成独立的 HandleFile 意图。事件遍历完成后,按信号位优先级依次生成意图,始终兜底一条 Idle + NoOp 用于证明链路通畅。


2.2 aios-action — ActionExecutor 骨架 (crates/aios-action/)

新增文件: src/lib.rs (85 行)

实现 aios_spec::traits::ActionExecutor trait。当前为骨架,所有操作通过 tracing 记录,后续对接真实 syscall。

实现细节

pub struct DefaultActionExecutor;

impl ActionExecutor for DefaultActionExecutor {
    fn execute(&self, action: &SuggestedAction) -> ActionResult;
}

execute(&self, action: &SuggestedAction) -> ActionResult (crates/aios-action/src/lib.rs:22)

Instant::now() 标记开始时间,按 action.action_type 分发到五个分支:

  • PreWarmProcess — 要求 target 非空,缺失时返回 success: false。占位日志记录目标 app 和紧迫度。
  • PrefetchFile — 占位日志,不要求 target 必填。
  • KeepAlive — 不强制 target,无目标时静默跳过(仍返回 success)。
  • ReleaseMemory — 占位日志。
  • NoOp — 直接返回成功,日志级别为 debug

每条结果包含 latency_us(微秒级计时),确保即使骨架阶段也有可度量的耗时统计。


2.3 aios-core — WindowAggregator (crates/aios-core/src/context_builder.rs)

新增文件: src/context_builder.rs (171 行)

SanitizedEvent 按固定时间窗口 (默认 10s) 聚合为 StructuredContext,这是发送给 LLM 前的最后一步。

API

pub struct WindowAggregator {
    buffer: Vec<SanitizedEvent>,
    window_secs: u64,
    window_start_ms: i64,
}

impl WindowAggregator {
    pub fn new(window_secs: u64, now_ms: i64) -> Self;
    pub fn push(&mut self, event: SanitizedEvent);
    pub fn len(&self) -> usize;
    pub fn is_empty(&self) -> bool;
    pub fn is_expired(&self, now_ms: i64) -> bool;
    pub fn close(&mut self, now_ms: i64) -> Option<StructuredContext>;
}

方法细节

new(window_secs: u64, now_ms: i64) -> Self (crates/aios-core/src/context_builder.rs:25)

以当前时间作为窗口起点,初始化空缓冲区。

push(&mut self, event: SanitizedEvent) (crates/aios-core/src/context_builder.rs:35)

追加单个脱敏事件到当前窗口。不做任何过滤——所有事件均被保留,由 LLM 端按上下文窗口做统计推断。

close(&mut self, now_ms: i64) -> Option<StructuredContext> (crates/aios-core/src/context_builder.rs:52)

关闭当前窗口:取走全部事件(std::mem::take),调用 build_summary() 生成摘要,构建 StructuredContext 并重置窗口起点。空窗口返回 None

build_summary(events: &[SanitizedEvent]) -> ContextSummary (crates/aios-core/src/context_builder.rs:91)

从事件序列构建聚合摘要: - foreground_apps — 从 ProcessResourceInterAppInteraction 事件的 package_name / source_package 提取,去重 - notified_apps — 从 Notification 事件的 source_package 提取,去重 - all_semantic_hints — 从 Notification 事件的 semantic_hints 汇总,去重 - file_activity — 从 FileActivityextension_category 计数 (HashMap<ExtensionCategory, u32>) - latest_system_status — 取窗口内最后一条 SystemStatus 事件的快照 - source_tier — 若窗口内存在任一条 Daemon 级事件则升为 Daemon,否则 PublicApi


三、重构的模块

3.1 daemon 主循环 (crates/aios-daemon/src/main.rs)

变更: 165 行 → 264 行 (重构, 后从 aios-collector 迁移至 aios-daemon — 见 3.3)

从单一采集循环重构为 2-task tokio 管道:

Task 1 (采集): tokio::spawn  → collection_loop
Task 2 (处理): main task     → processing_loop

采集任务 (task 1)

原主循环的采集逻辑完整迁移至独立的 async block (crates/aios-daemon/src/main.rs)。行为不变:每 100ms 扫描 /proc 差分 + Binder eBPF 轮询,每 30s 采集系统状态。事件通过 raw_events_tx.send() 推送到处理管道。退出信号通过 broadcast::Receiver::try_recv() 非阻塞轮询。

处理管道 (task 2)

运行在主 task 上 (crates/aios-daemon/src/main.rs)。核心循环使用 tokio::select! 等待三路事件:

  1. shutdown_rx.recv() — 优雅退出
  2. bus.raw_events_rx.recv() — 接收原始事件 → sanitizer.sanitize()window.push()
  3. tokio::time::sleep — 窗口到期的 deadline 定时器触发窗口关闭

窗口关闭后调用 process_window() (crates/aios-daemon/src/main.rs),执行 DecisionRouter::evaluate() → PolicyEngine::evaluate_batch() → executor.execute_batch() 完整链路。所有步骤均通过 tracing::info!/tracing::warn!/tracing::debug! 打点。

3.2 aios-spec 微调

文件 变更 原因
src/lib.rs traits 模块新增 pub use executor::ActionResult aios-action 实现 ActionExecutor 需要 ActionResult 类型
src/event.rs ExtensionCategory derive 增加 Hash context_builder 需要 HashMap<ExtensionCategory, u32> 做文件活动计数

3.3 依赖层级重排 — 恢复计划架构

问题: v0.2 初始合并时,aios-collector 直接依赖 aios-agent 以使用 MockCloudProxy,违反了 CLAUDE.md 规定的「上层依赖下层」单向层级:

aios-cli / aios-agent  (业务逻辑 / LLM 代理)
   aios-collector         (平台适配)
   aios-action           (资源生命周期)
    aios-core            (动作总线、隐私、策略)
    aios-spec            (数据类型 & traits)

修正 (5 处变更):

文件 变更 说明
crates/aios-collector/Cargo.toml 移除 aios-agent 依赖 + [[bin]] collector 回归纯库角色
crates/aios-daemon/Cargo.toml 新增 aios-collector, aios-core, aios-action, aios-agent, tokio, tracing-subscriber, anyhow, libc 依赖 + [[bin]] daemon 独立为运行时宿主
crates/aios-daemon/src/main.rs 新建 (从旧 dipecsd 入口迁移, 264 行) daemon 二进制归属 aios-daemon
crates/aios-collector/src/main.rs 删除
docs/src/design/crates-map.md 更新 daemon 二进制路径 → crates/aios-daemon/src/main.rs 文档与代码一致

修正后依赖方向正确: aios-spec → collector/core/action/agent → aios-daemon

验证: cargo tree -p aios-collector | grep -E "aios-agent|aios-cli" 无输出。


四、测试覆盖

v0.1 遗留测试 (5 个)

文件: crates/aios-core/tests/privacy_airgap_test.rs (141 行)

测试 描述 验证点
test_notification_file_detection 飞书收到 PDF 文件通知 脱敏后正确检出 SemanticHint::FileMention,原文不可访问
test_notification_image_detection 微信收到照片 脱敏后正确检出 SemanticHint::ImageMention
test_fs_classification 下载 report.pdf /Download/report.pdfExtensionCategory::Document
test_binder_notification_detection Binder 通知事务 enqueueNotificationWithTagInteractionType::NotifyPost
test_prefixed_variable_warning_suppression 编译期验证 确保 _ 前缀变量不触发 clippy 警告

v0.2 新增测试 (58 个)

MockCloudProxy (crates/aios-agent/tests/mock_cloud_proxy_test.rs, 9 个)

测试 验证点
test_empty_window_returns_idle 空窗口 → Idle + NoOp 兜底
test_file_mention_triggers_open_app 通知含 FileMention → OpenApp + PreWarmProcess
test_activity_launch_triggers_switch_to_app ActivityLaunch → SwitchToApp + 双动作
test_file_activity_generates_handle_file FileActivity(Document) → HandleFile + PrefetchFile
test_multiple_file_activities_generate_multiple_intents 3 类文件活动 → 3 条独立 HandleFile 意图
test_screen_on_triggers_keepalive 屏幕 Interactive → Idle + KeepAlive
test_low_battery_triggers_release_memory 电量 < 20% → Idle + ReleaseMemory
test_normal_battery_no_release 电量 85% → 不触发 ReleaseMemory
test_combined_signals_all_detected 5 种信号同时存在 → 全部检出

DefaultActionExecutor (crates/aios-action/tests/action_executor_test.rs, 14 个)

测试 验证点
test_prewarm_with_target_succeeds PreWarmProcess + target → success=true
test_prewarm_without_target_fails PreWarmProcess 缺 target → success=false
test_prefetch_file_succeeds / test_prefetch_file_no_target_succeeds PrefetchFile 有无 target 均成功
test_keep_alive_*_succeeds (2 个) KeepAlive 有无 target 均成功 (静默跳过)
test_release_memory_*_succeeds (2 个) ReleaseMemory 始终成功
test_noop_succeeds NoOp → success=true
test_execute_batch_* (2 个) 批量执行返回正确数量和顺序
test_result_contains_action_name ActionResult.action_type 字段正确
test_result_preserves_target ActionResult.target 字段保留
test_latency_is_microseconds 骨架执行耗时 < 1ms

WindowAggregator (crates/aios-core/tests/context_builder_test.rs, 17 个)

测试 验证点
test_new_window_is_empty 新窗口 is_empty=true, len=0
test_push_increases_length push → len 递增
test_window_not_expired_before_deadline 窗口到期前 is_expired=false
test_window_expired_after_deadline / at_exact 窗口到期后 / 精确边界 is_expired=true
test_close_empty_window_returns_none 空窗口 close → None
test_close_non_empty_returns_context 非空窗口 close → StructuredContext (含正确时间戳)
test_close_resets_buffer close 后窗口变空, len=0
test_close_updates_window_start close 后新窗口起点刷新
test_summary_foreground_apps Process + InterApp → foreground_apps 聚合去重
test_summary_notified_apps Notification → notified_apps 聚合去重
test_summary_semantic_hints 多通知 → all_semantic_hints 聚合去重
test_summary_file_activity_counts 文件活动 → file_activity 计数 (HashMap)
test_summary_latest_system_status 多条 SystemStatus → 取最新值
test_summary_source_tier_daemon_wins PublicApi + Daemon 共存 → Daemon
test_summary_source_tier_public_api_only 仅 PublicApi → PublicApi
test_multiple_windows_cycle 两个连续窗口正确隔离

PolicyEngine (crates/aios-core/tests/policy_engine_test.rs, 11 个)

测试 验证点
test_low_risk_approved_by_default Low Risk → approved=true
test_medium_risk_rejected_by_default Medium Risk > max(Low) → rejected
test_high_risk_rejected_by_default High Risk → rejected
test_medium_risk_approved_with_relaxed_config 配置放宽到 Medium → approved
test_low_confidence_rejected confidence < 0.3 → rejected
test_confidence_at_boundary_approved confidence = 0.3 → approved (精确边界)
test_deferred_urgency_filtered Deferred 紧迫度 → 动作被过滤
test_blocked_action_filtered 黑名单 ReleaseMemory → 动作被过滤
test_max_actions_per_batch_enforced 3 动作 + max=2 → 截断为 2
test_evaluate_batch_mixed_results 3 意图 (ok/high-risk/low-conf) → 混合决策正确
test_approved_intent_preserves_actions 通过的意图保留全部动作

ActionBus (crates/aios-core/tests/action_bus_test.rs, 7 个)

测试 验证点
test_push_raw_event_succeeds / _received 原始事件发送和接收
test_push_intent_succeeds / _received 意图批次发送和接收
test_channel_closed_after_rx_dropped rx drop 后 send 返回 Err
test_intent_channel_closed_after_rx_dropped intent_rx drop 后 intent_tx.send 失败
test_action_bus_default_creates ActionBus::default() 通道可用

五、编译与测试验证

全量检查 (一键命令)

# 格式检查
cargo fmt --all -- --check

# Clippy 严格模式 (warnings as errors)
cargo clippy --workspace --all-targets -- -D warnings

# 全量测试 (当前: 63 passed; 0 failed)
cargo test --workspace

# 类型检查
cargo check --workspace --all-targets

CI 等效命令 (推荐在提交前执行)

./scripts/check-all.sh

测试分布总览

crates/aios-agent/tests/mock_cloud_proxy_test.rs    |   9 tests  (意图生成 6 种信号 + 组合)
crates/aios-action/tests/action_executor_test.rs    |  14 tests  (5 种动作 + batch + 字段)
crates/aios-core/tests/privacy_airgap_test.rs       |   5 tests  (脱敏 v0.1 遗留)
crates/aios-core/tests/context_builder_test.rs      |  17 tests  (窗口生命周期 + 聚合)
crates/aios-core/tests/policy_engine_test.rs        |  11 tests  (风险/置信度/动作过滤)
crates/aios-core/tests/action_bus_test.rs           |   7 tests  (事件/意图通道)
────────────────────────────────────────────────────────────────
  Total                                              |  63 tests; 0 failed

快速确认一切正常的步骤

  1. 编译: cargo check --workspace → 无 error
  2. 格式: cargo fmt --all -- --check → 无输出 (表示格式正确)
  3. Lint: cargo clippy --workspace --all-targets -- -D warnings → 无 warning
  4. 测试: cargo test --workspace63 passed; 0 failed
  5. 交叉编译 (可选): source scripts/setup-env.sh && cargo android-release → 编译成功
  6. 依赖审计 (可选): cargo deny check → 0 个许可/安全违规

预期输出: 以上 6 步全部零错误 / 零警告 / 测试全绿。


六、依赖变更

变更 位置 说明
aios-agent workspace dep (新增) Cargo.toml agent crate 进入 workspace
aios-action workspace dep (新增) Cargo.toml action crate 进入 workspace
aios-collector, aios-core, aios-action (新增) crates/aios-agent/Cargo.toml agent 依赖下层所有 crate (符合层级)
tokio, tracing-subscriber, anyhow, libc (新增) crates/aios-daemon/Cargo.toml daemon 二进制需要
aios-agent (移除) crates/aios-collector/Cargo.toml 修正反向依赖 (见 3.3 节)
aios-spec + tracing + uuid (保留) crates/aios-agent/Cargo.toml MockCloudProxy 实现
aios-spec + tracing + libc crates/aios-action/Cargo.toml ActionExecutor 骨架 (libc 预留给后续 syscall)

所有依赖均来自 workspace,无新增外部 crate。


七、已知缺口 (后续版本)

v0.2 测试状态: 6 个测试文件, 63 个测试, 全部通过。覆盖 MockCloudProxy / ActionExecutor / WindowAggregator / PolicyEngine / ActionBus / PrivacyAirGap。

模块 状态 计划
aios-agent CloudProxy (HTTPS) Mock 已就绪 替换为 reqwest + rustls 真实 LLM 通信
aios-action ActionExecutor (syscall) 骨架已就绪 对接 /proc/pid/oom_score_adj, posix_fadvise, process_madvise
FanotifyMonitor 未实现 FsAccessEvent 类型已有,采集器待写
NotificationBridge (Kotlin → Rust) 未实现 需要 JNI bridge + NotificationListenerService
GoldenTrace 录制与回放 TraceEngine 已有,未接入主循环 需在 process_window 中集成录制
Android 交叉编译 配置就绪 (.cargo/config.toml) 真机/模拟器上跑 dipecsd --no-daemon --verbose

八、文件变更清单

  Cargo.lock                                 (同步)
  Cargo.toml                          |   2 + (aios-agent, aios-action workspace dep)
  crates/aios-daemon/Cargo.toml       |   8 + (依赖 + [[bin]])
  crates/aios-agent/src/lib.rs        | 212 +++ (MockCloudProxy 重写)
  crates/aios-daemon/src/main.rs      | 264 +++ (daemon 二进制, 从 collector 迁移)
  crates/aios-agent/tests/mock_cloud_proxy_test.rs | 300 +++ (新增: 9 个测试)
  crates/aios-core/src/context_builder.rs | 171 +++ (WindowAggregator 新增)
  crates/aios-core/src/lib.rs         |   1 + (pub mod context_builder)
  crates/aios-core/tests/context_builder_test.rs  | 271 +++ (新增: 17 个测试)
  crates/aios-core/tests/policy_engine_test.rs    | 228 +++ (新增: 11 个测试)
  crates/aios-core/tests/action_bus_test.rs       | 112 +++ (新增: 7 个测试)
  crates/aios-action/Cargo.toml       |   3 + (依赖)
  crates/aios-action/src/lib.rs       |  92 +++ (DefaultActionExecutor 重写)
  crates/aios-action/tests/action_executor_test.rs | 155 +++ (新增: 14 个测试)
  crates/aios-collector/Cargo.toml      |   1 - (移除 aios-agent 依赖 / [[bin]])
  crates/aios-collector/src/main.rs     |   0 - (删除, 迁移至 aios-agent)
  crates/aios-spec/src/event.rs       |   2 +- (ExtensionCategory +Hash)
  crates/aios-spec/src/lib.rs         |   2 +- (导出 ActionResult)
  CLAUDE.md                           |   2 +- (daemon 二进制路径更新)
 ─────────────────────────────────────────────────────────────────
  19 files, 63 tests, all passing