使用预览：

```java
// 1. 创建执行器
WorkflowExecutor workflow = WorkflowExecutor.of(engine, controller, repository);

// 2. 认领任务（认领有权限操作的待处理任务）
Task current = workflow.claimTask(graph, context);
if (current != null) {
    // 3. 提交任务处理
    workflow.submitTask(current, TaskAction.FORWARD, context);
}

// 4. 查找后续可能任务（下一步）
Collection<Task> nextTasks = workflow.findNextTasks(graph, context);
```


### 1、WorkflowExecutor 接口说明：


| 方法名                 | 核心行为        | 副作用        | 开发者视角语义                                                              |
|---------------------|-------------|------------|----------------------------------------------------------------------|
| claimTask           | 权限匹配 + 状态激活 | 写入 WAITING | 认领：从起点开始 eval。若碰撞到 UNKNOWN 节点且 isOperatable 为真，则通过 statePut 将其激活为 WAITING。它是任务从“理论存在”变为“数据库待办”的转折点。如果没有则为 null。              |
| findTask            | 逻辑位置探测      | /          | 查询：模拟执行流程图。返回当前路径上第一个活跃节点（状态为 WAITING/COMPLETED/TERMINATED）。它不校验权限，只负责告诉调用者“流程逻辑上现在停在哪”。理论上总能找到一个。 |
| findNextTasks       | 全量路径扫描      |            | 预测下一步：深度遍历所有可能的分支。忽略权限和当前停顿，扫描所有 UNKNOWN 或 WAITING 的任务点。常用于渲染流程图的“预测轨迹”或处理并行网关（Join/Fork）的探测。                               |
| getState            | 仓库快照查询      | /          | 查看状态：直接根据 context 和 nodeId 从 StateRepository 中拉取状态枚举。它是最轻量级的检查手段。                                   |
| submitTask          | 状态机驱动       | 写入最新状态     | 流程推进：流转的唯一入口。根据 TaskAction 执行 forwardHandle 或 backHandle。它会触发 postHandleTask 业务钩子，并持久化新状态，从而改变后续 findTask 的探测结果。                                                        |



### 2、submitTask(TaskAction) 效果说明：


| 动作 (TaskAction)  | 中间节点处理 (A, B) | 目标节点 C 的最终状态   | 流程停留在哪里？ | 业务语义                                 |
|--------------|---------------|----------------|----------|--------------------------------------|
| FORWARD      | /             | COMPLETED      | C 的下一步   | 正常办理：完成当前节点并流转。                      |
| FORWARD_JUMP | 标记为 COMPLETED | WAITING        | 停在 C     | 跨级指派：跳过中间环节，直接让 C 变为待办。              |
| BACK         | /             | REMOVED(无状态)   | C 的前一步   | 常规退回：撤销当前步，使前驱节点重新激活。                |
| BACK_JUMP    | 状态被 REMOVED   | WAITING        | 停在 C     | 指定驳回：撤销中间节点状态，要求 C 重办。               |
| RESTART      | 全部 REMOVED    | REMOVED        | 流程起点     | 全线撤回：清空所有状态，回到 StartNode。            |
| TERMINATE    | /             | TERMINATE      | 停在 C     | 终止流程：之后 forwardHandle 会检测到该状态并停止。    |



### 3、WorkflowExecutor 接口参考


```java
package org.noear.solon.flow.workflow;

import org.noear.solon.flow.FlowContext;
import org.noear.solon.flow.FlowEngine;
import org.noear.solon.flow.Graph;
import org.noear.solon.flow.Node;
import org.noear.solon.lang.Nullable;
import org.noear.solon.lang.Preview;

import java.util.Collection;

/**
 * 工作流执行器
 *
 * <p>提供工作流任务的执行框架能力，包括：
 * 1. 任务提交执行（前进、后退、跳转等）
 * 2. 当前活动任务匹配
 * 3. 后续可达任务查找
 *
 * <p>典型使用场景：
 * <pre>{@code
 * // 1. 创建执行器
 * WorkflowExecutor workflow = WorkflowExecutor.of(engine, controller, repository);
 *
 * // 2. 认领任务（检查是否有可操作的待处理任务）
 * Task current = workflow.claimTask(graph, context);
 * if (current != null) {
 *     // 3. 提交任务处理
 *     workflow.submitTask(current, TaskAction.FORWARD, context);
 * }
 *
 * // 4. 查找后续可能任务（下一步）
 * Collection<Task> nextTasks = workflow.findNextTasks(graph, context);
 * }</pre>
 *
 * <p><b>注意：</b>本执行器专注于流程执行逻辑，不包含实例管理等业务功能。
 *
 * @since 3.8.1
 */
@Preview("3.4")
public interface WorkflowExecutor {
    static WorkflowExecutor of(FlowEngine engine, StateController stateController, StateRepository stateRepository) {
        return new WorkflowExecutorDefault(engine, stateController, stateRepository);
    }

    /**
     * 流程引擎
     */
    FlowEngine engine();

    /**
     * 状态控制器
     */
    StateController stateController();

    /**
     * 状态仓库
     */
    StateRepository stateRepository();


    /// ////////////////////////////////


    /**
     * 认领当前活动任务（权限匹配，并锁定状态为等待）
     *
     * @param graphId 图id
     * @param context 流上下文（要有人员配置）
     */
    @Nullable
    default Task claimTask(String graphId, FlowContext context) {
        return claimTask(engine().getGraphOrThrow(graphId), context);
    }

    /**
     * 认领当前活动任务（权限匹配，并锁定状态为等待）
     *
     * @param graph   图
     * @param context 流上下文（要有人员配置）
     */
    @Nullable
    Task claimTask(Graph graph, FlowContext context);

    /**
     * 寻找当前确定的任务（逻辑探测）
     *
     * @param graphId 图id
     * @param context 流上下文（要有人员配置）
     */
    @Nullable
    default Task findTask(String graphId, FlowContext context) {
        return findTask(engine().getGraphOrThrow(graphId), context);
    }

    /**
     * 寻找当前确定的任务（逻辑探测）
     *
     * @param graph   图
     * @param context 流上下文（要有人员配置）
     */
    @Nullable
    Task findTask(Graph graph, FlowContext context);

    /**
     * 寻找下一步可能的任务列表（逻辑探测）
     *
     * @param graphId 图id
     * @param context 流上下文（不需要有人员配置）
     */
    default Collection<Task> findNextTasks(String graphId, FlowContext context) {
        return findNextTasks(engine().getGraphOrThrow(graphId), context);
    }

    /**
     * 寻找下一步可能的任务列表（寻找所有可能性）
     *
     * @param graph   图
     * @param context 流上下文（逻辑探测）
     */
    Collection<Task> findNextTasks(Graph graph, FlowContext context);


    /// ////////////////////////////////

    /**
     * 获取状态
     */
    TaskState getState(Node node, FlowContext context);

    /// ////////////////////////////////

    /**
     * 提交任务（如果当前任务为等待介入）
     *
     * @param task    任务
     * @param action  动作
     * @param context 流上下文
     */
    boolean submitTaskIfWaiting(Task task, TaskAction action, FlowContext context);

    /**
     * 提交任务
     *
     * @param task    任务
     * @param action  动作
     * @param context 流上下文
     */
    default void submitTask(Task task, TaskAction action, FlowContext context) {
        submitTask(task.getRootGraph(), task.getNode(), action, context);
    }

    /**
     * 提交任务
     *
     * @param graphId 图id
     * @param nodeId  节点id
     * @param action  动作
     * @param context 流上下文
     */
    default void submitTask(String graphId, String nodeId, TaskAction action, FlowContext context) {
        submitTask(engine().getGraphOrThrow(graphId), nodeId, action, context);
    }

    /**
     * 提交任务
     *
     * @param graph   图
     * @param nodeId  节点id
     * @param action  动作
     * @param context 流上下文
     */
    default void submitTask(Graph graph, String nodeId, TaskAction action, FlowContext context) {
        submitTask(graph, graph.getNodeOrThrow(nodeId), action, context);
    }

    /**
     * 提交任务
     *
     * @param graph   图
     * @param node    节点
     * @param action  动作
     * @param context 流上下文
     */
    void submitTask(Graph graph, Node node, TaskAction action, FlowContext context);
}
```






