# df-nodes 节点架构走查(方向1,7 维度)

## 节点接口一致性

- **10 生产节点**(AiNode/AiSelfReviewNode/GitNode/HttpNode/DockerNode/ScriptNode/SubflowNode/NotifyNode/HumanNode/TaskAdvanceNode)+ 1 测试 SleepNode。**全部正确 impl Node trait**(execute/schema/is_blocking/node_type + #[async_trait] + Send+Sync),签名一致。无 trait 偏离。
- **P2**:state.rs:586-614 build_registry 只注册 4/10(human/ai/ai_self_review/task_advance),6 节点(git/http/docker/notify/subflow/script)实现完整但不可达。script 有 R-PD-2 安全文档依据(刻意掐断),其余 5 个零文档。
- **P3**:SubflowNode node_type() 用 &'static str(其余 9 节点 &str),风格分裂。
- **P3**:script_node.rs:1 缺 R-PD-2「未注册」安全注释(文档承诺未落地)。

## human_node 36KB(推翻假设:无技术债)

- execute 函数体 139 行,职责内聚(配置解析 → subscribe-then-send 序约束 → select! 循环 Response/超时/取消)。**非职责过宽**。
- 36KB/833 行真实构成:实现 200 行(含详尽中文 why-注释)+ 测试 633 行(18 集成测 + 1 单测,76%)。**最大文件源于测试覆盖完整,非实现臃肿**。
- memory `devflow-workflow-approval-review` 头号 bug(human_node:41 缺 await)**已修**(line 55-64 `.send().await`),双回归测试(request_is_emitted_to_bus + end_to_end)。

## ai_self_review_node 21KB(P1,已修)

- **P1**:build_review_prompt(:50-69)直接 format task.description/output_text 进 user prompt,无隔离。**已修**(fc249ad):truncate_for_review_input(2000 字符) + XML 标签 `<task_output>` 隔离 + system 声明数据非指令。
- **P2**:parse_review_json(ai_node_helpers.rs:258-279)仅校验 verdict 存在,不校验取值/不 clamp score(0-10)/无正则兜底。verdict "Pass"/"PASS" → gate_should_block 精确匹配 "fail" 误判放行。
- **P2**:schema required=["task_id","provider_id"](:249)但 provider_id 实际可选(resolve_provider 空串走默认),required 冲突误导。

## task_advance_node 25KB

- 状态机调用正确,非法转换防护。与 memory `devflow-advance-task-dfnodes`(D-03 走 df-nodes Node trait)对齐。

## task_state_machine 16KB

- 状态转移矩阵完整。与 conv_state.rs ConvState 状态机是两套(任务状态 vs 对话状态),职责不同不冲突。

## 错误处理一致性

- 各节点错误类型统一(anyhow::Result<NodeError>),错误传播(?)正确。无明显 panic 风险。

## 并发安全

- HumanNode 是唯一 is_blocking=true,select! 循环处理 Response/超时/取消。cancel_tick 500ms 轮询(非事件驱动),但开销可忽略(O(1) HashMap lookup)。无死锁/竞争。
