meta: name: node_state_machine version: 0.1 language: zh-CN desc: "节点状态机配置(用于驱动/校验未来的状态机组件)" # 命名约定(配置内唯一真名;图上不再有 display/别名): # - Sxx: State / PseudoState(节点) # - Exx: Event(事件) # - 事件分支由渲染器在边上追加 a/b/c...(对应 outcomes 顺序) id_convention: state_prefix: "S" event_prefix: "E" # Variables are computed by the caller and passed into the state machine. # Rule: the YAML never directly mutates "peer" nodes. Cross-node changes must be # represented as separate invocations with different inputs. context: is_create_zombie: { type: bool, desc: "初始化时判定为 CREATE 僵尸:action=CREATE 且 (status=FAILED 或 data_id 为空)" } has_binding_record: { type: bool, desc: "binding_manager 里存在绑定记录 (remote_id/local_id 非空)" } core_binding_result: { type: enum, values: [NORMAL, WARNING, ABNORMAL], desc: "SyncDecisionEngine.determine_core_status() 给本节点的结果(仅在 has_binding_record=true 时有效)" } peer_core_binding_result: { type: enum, values: [NORMAL, WARNING, ABNORMAL], desc: "SyncDecisionEngine.determine_core_status() 给对方节点的结果(用于静态约束 core matrix 对称性)" } data_present: { type: bool, desc: "node.get_data() 非空" } has_depend_fields: { type: bool, desc: "config.depend_fields 非空" } dep_satisfied: { type: bool, desc: "依赖满足:空依赖值跳过;非空依赖值必须能在 collection 中按 data_id 找到且节点状态可用" } auto_bind_enabled: { type: bool, desc: "config.auto_bind && auto_bind_fields 非空" } auto_bind_outcome: type: enum values: [ONE_TO_ONE, AMBIGUOUS, ZERO, KEY_MISSING, KEY_ID_RESOLVE_FAIL, DATA_MISSING] desc: "自动绑定结果(由业务代码完成全集搜索+去噪后 1:1 判定)" create_enabled: { type: bool, desc: "create() 是否对当前方向启用 (local_orphan_action/remote_orphan_action)" } create_id_resolve_ok: { type: bool, desc: "IDResolver.resolve_and_validate() 是否成功" } spawn_success: { type: bool, desc: "创建副作用(spawn + bind)是否成功" } update_enabled: { type: bool, desc: "update() 是否启用 (update_direction != NONE)" } target_has_data_id: { type: bool, desc: "UPDATE 目标节点 data_id 非空" } update_id_resolve_ok: { type: bool, desc: "UPDATE 前 IDResolver.resolve_and_validate() 是否成功" } has_diff: { type: bool, desc: "needs_update_check 判定有差异" } handler_result: type: enum values: [SUCCESS, FAILED, SKIPPED, IN_PROGRESS] desc: "TaskResult.status" poll_timeout: { type: bool, desc: "异步轮询超过 max_retries" } execute_action: type: enum values: [CREATE, UPDATE, DELETE, NONE] desc: "E40 执行时的动作类型(用于区分 SKIPPED 的落点)" # State IDs are for visualization and static validation. # NOTE: 本状态机按“加载时清空执行状态,再开始本轮”建模: # - 加载/初始化后,稳态节点的 status 统一回到 PENDING # - 上一轮遗留的 FAILED/SUCCESS 等不作为本轮的入口状态 states: # --- Stable entry to bind (after init reset + zombie cleanup) --- S00: binding_status: UNCHECKED action: NONE status: PENDING data_id_exist: true desc: | 进入 bind 前的唯一起点 binding_status: UNCHECKED action: NONE status: PENDING data_id_exist: true # --- Bind results --- S01: binding_status: NORMAL action: NONE status: PENDING data_id_exist: true desc: | 绑定正常(待后续 update 检查) binding_status: NORMAL action: NONE status: PENDING data_id_exist: true S02: binding_status: MISSING action: NONE status: PENDING data_id_exist: true desc: | 孤儿节点(可能进入 create / auto_bind / delete) binding_status: MISSING action: NONE status: PENDING data_id_exist: true S03: binding_status: ABNORMAL action: NONE status: PENDING data_id_exist: true desc: | 数据损坏/缺失(阻断态,需人工) binding_status: ABNORMAL action: NONE status: PENDING data_id_exist: true S04: binding_status: WARNING action: NONE status: PENDING data_id_exist: true desc: | 不可自动处理(阻断态,需人工) binding_status: WARNING action: NONE status: PENDING data_id_exist: true S05: binding_status: DEPENDENCY_ERROR action: NONE status: PENDING data_id_exist: true desc: | 依赖项不满足/ID解析失败(阻断态) binding_status: DEPENDENCY_ERROR action: NONE status: PENDING data_id_exist: true # --- Create & Update prepared actions (target-side nodes) --- S06: binding_status: NORMAL action: CREATE status: PENDING data_id_exist: false shape: pseudo desc: | 待执行 CREATE(执行入口) binding_status: NORMAL action: CREATE status: PENDING data_id_exist: false S07: binding_status: NORMAL action: UPDATE status: PENDING data_id_exist: true desc: | 准备更新 binding_status: NORMAL action: UPDATE status: PENDING data_id_exist: true S08: binding_status: NORMAL action: UPDATE status: PRECONDITION_FAILED data_id_exist: [false, true] desc: | 更新前置失败(缺 data_id / 依赖ID未解析等) binding_status: NORMAL action: UPDATE status: PRECONDITION_FAILED data_id_exist: false | true S09: binding_status: NORMAL action: DELETE status: PENDING data_id_exist: true desc: | 待执行 DELETE(执行入口) binding_status: NORMAL action: DELETE status: PENDING data_id_exist: true # --- Sync results --- S10C: binding_status: NORMAL action: CREATE status: IN_PROGRESS data_id_exist: false desc: | CREATE 异步执行中 binding_status: NORMAL action: CREATE status: IN_PROGRESS data_id_exist: false S10U: binding_status: NORMAL action: UPDATE status: IN_PROGRESS data_id_exist: true desc: | UPDATE 异步执行中 binding_status: NORMAL action: UPDATE status: IN_PROGRESS data_id_exist: true S10D: binding_status: NORMAL action: DELETE status: IN_PROGRESS data_id_exist: true desc: | DELETE 异步执行中 binding_status: NORMAL action: DELETE status: IN_PROGRESS data_id_exist: true S11C: binding_status: NORMAL action: CREATE status: SUCCESS data_id_exist: true desc: | CREATE 执行成功 binding_status: NORMAL action: CREATE status: SUCCESS data_id_exist: true S11U: binding_status: NORMAL action: UPDATE status: SUCCESS data_id_exist: true desc: | UPDATE 执行成功 binding_status: NORMAL action: UPDATE status: SUCCESS data_id_exist: true S11D: binding_status: NORMAL action: DELETE status: SUCCESS data_id_exist: true desc: | DELETE 执行成功(随后删除节点) binding_status: NORMAL action: DELETE status: SUCCESS data_id_exist: true S12C: binding_status: NORMAL action: CREATE status: FAILED data_id_exist: [false, true] desc: | CREATE 执行失败 binding_status: NORMAL action: CREATE status: FAILED data_id_exist: false | true S12U: binding_status: NORMAL action: UPDATE status: FAILED data_id_exist: [false, true] desc: | UPDATE 执行失败 binding_status: NORMAL action: UPDATE status: FAILED data_id_exist: false | true S12D: binding_status: NORMAL action: DELETE status: FAILED data_id_exist: [false, true] desc: | DELETE 执行失败 binding_status: NORMAL action: DELETE status: FAILED data_id_exist: false | true S13: binding_status: PEER_CREATING action: NONE status: PENDING data_id_exist: true desc: | 对侧创建进行中(本侧等待提交) binding_status: PEER_CREATING action: NONE status: PENDING data_id_exist: true # Handler 在 update 路径中可能把 action 降级为 NONE 并返回 SKIPPED。 # NOTE: 这会产生 (NORMAL, NONE, SKIPPED),并且该节点会被统计到 none 列。 S14: binding_status: NORMAL action: NONE status: SKIPPED data_id_exist: true desc: | 更新被跳过(执行时降级为 NONE) binding_status: NORMAL action: NONE status: SKIPPED data_id_exist: true pseudo_states: S15: desc: "节点被清理删除(zombie cleanup)" S16: desc: "持久化加载输入态:本轮 E01 的输入节点集合(可包含上轮遗留与已稳定节点)" S17: desc: "加载异常隔离态:持久化枚举非法,保留错误供人工处理,不进入自动流程" stages: bootstrap: desc: "启动/初始化(仅针对持久化加载出的节点):僵尸清理与归并到 S00" entry_states: [S16] exit_states: [S00, S15] bind: desc: "绑定判定:core matrix +(可选)依赖检查 +(可选)自动绑定;stage 仅约束边界,不要求内部顺序" entry_states: [S00] exit_states: [S01, S02, S03, S04, S05, S13] create_prepare: desc: "Create: 从 MISSING 源节点发起创建请求并在副作用提交后归并" entry_states: [S02, S13] exit_states: [S01, S02, S04, S05, S09, S13] update_prepare: desc: "Update: 检测差异并在目标节点上设置 UPDATE/PRECONDITION_FAILED" entry_states: [S01] exit_states: [S01, S07, S08] post_create_ready: desc: "创建成功后归并:CREATE 成功节点回到 NORMAL/NONE/PENDING,作为 update 起点" entry_states: [S11C] exit_states: [S01] sync_execute: desc: "Sync: DataSource 调用 handler,根据 TaskResult 更新 status;部分 handler 可能降级 action" entry_states: [S06, S07, S09, S10C, S10U, S10D] exit_states: [S10C, S10U, S10D, S11C, S11U, S11D, S12C, S12U, S12D, S14] transitions: E01: stage: bootstrap desc: "初始化:删CREATE僵尸;其余重置后进入起点" from: [S16] outcomes: - when: { is_create_zombie: true } to: S15 - when: { is_create_zombie: false } to: S00 # --- Bind phase1 core --- E10: stage: bind desc: "核心绑定判定:有绑定按core结果分流;无绑定→MISSING" from: [S00] outcomes: - when: { has_binding_record: true, core_binding_result: NORMAL, peer_core_binding_result: NORMAL } to: S01 emit: note: "绑定关系一致,进入正常态" - when: { has_binding_record: true, core_binding_result: WARNING, peer_core_binding_result: ABNORMAL } to: S04 emit: note: "对端异常,本端标记WARNING" - when: { has_binding_record: true, core_binding_result: ABNORMAL, peer_core_binding_result: WARNING } to: S03 emit: note: "本端异常,进入ABNORMAL" - when: { has_binding_record: true, core_binding_result: ABNORMAL, peer_core_binding_result: ABNORMAL } to: S03 emit: note: "双方异常,进入ABNORMAL" - when: { has_binding_record: false } to: S02 emit: note: "无绑定记录,标记为MISSING" # --- Bind phase2 dependency --- E15: stage: bind desc: "依赖检查:失败→阻断;缺少依赖配置→WARNING;通过→不变(不在图上画自环)" from: [S02] outcomes: - when: { has_depend_fields: false, data_present: true } to: S04 emit: note: "缺少依赖字段配置,无法自动处理" - when: { data_present: false } to: S03 emit: note: "节点数据为空或不存在" - when: { data_present: true, has_depend_fields: true, dep_satisfied: false } to: S05 emit: note: "依赖项不满足" # --- Bind phase3 auto bind --- E16: stage: bind desc: "自动绑定:1:1→NORMAL;歧义/缺字段/数据为空→阻断;N:0 且允许创建→S13 等待创建提交" from: [S02] outcomes: - when: { auto_bind_enabled: false } to: S04 emit: note: "自动绑定未启用" - when: { auto_bind_enabled: true, auto_bind_outcome: DATA_MISSING } to: S04 emit: note: "节点数据为空,无法自动绑定" - when: { auto_bind_enabled: true, auto_bind_outcome: ONE_TO_ONE } to: S01 emit: note: "自动绑定成功(1:1)" - when: { auto_bind_enabled: true, auto_bind_outcome: AMBIGUOUS } to: S04 emit: note: "存在多个候选节点,无法自动绑定" - when: { auto_bind_enabled: true, auto_bind_outcome: KEY_MISSING } to: S04 emit: note: "缺少业务键字段,无法自动绑定" - when: { auto_bind_enabled: true, auto_bind_outcome: KEY_ID_RESOLVE_FAIL } to: S05 emit: note: "业务键中的ID字段解析失败" - when: { auto_bind_enabled: true, auto_bind_outcome: ZERO, create_enabled: true } to: S13 emit: spawn_request: true spawn_target_node_state: S06 note: "自动绑定识别为需创建,进入创建提交中间态" - when: { auto_bind_enabled: true, auto_bind_outcome: ZERO, create_enabled: false } to: S04 emit: note: "未匹配到候选节点且不允许创建" # --- Create prepare --- E20: stage: create_prepare desc: "创建准备阶段2:spawn 成功则提交到 NORMAL;失败保持等待态(不迁移)" from: [S13] outcomes: - when: { spawn_success: true } to: S01 emit: note: "创建副作用提交成功" E21: stage: create_prepare desc: "创建依赖解析失败→DEPENDENCY_ERROR" from: [S02] outcomes: - when: { create_enabled: true, data_present: true, create_id_resolve_ok: false } to: S05 emit: note: "创建前依赖ID解析失败" E22: stage: create_prepare desc: "孤儿自删准备:从 MISSING 进入 DELETE 执行入口" from: [S02] outcomes: - when: {} to: S09 emit: note: "孤儿节点按策略进入自删" # --- Update prepare (target-side) --- E30: stage: update_prepare desc: "更新准备:缺data_id/依赖未解析→PRECONDITION_FAILED;有差异→UPDATE" from: [S01] outcomes: - when: { update_enabled: true, target_has_data_id: false } to: S08 emit: note: "目标节点缺少data_id" - when: { update_enabled: true, target_has_data_id: true, update_id_resolve_ok: false } to: S08 emit: note: "更新前依赖ID未解析" - when: { update_enabled: true, target_has_data_id: true, update_id_resolve_ok: true, has_diff: true } to: S07 emit: note: "检测到数据差异,准备更新" # --- Post-create normalization --- E41: stage: post_create_ready desc: "创建成功后归并到 update 起点" from: [S11C] outcomes: - when: { execute_action: CREATE } to: S01 emit: note: "创建成功后转入更新起点" # --- Sync execute (split by action) --- E40C_START: stage: sync_execute desc: "CREATE 执行入口:进入异步执行中" from: [S06] outcomes: - when: { handler_result: IN_PROGRESS } to: S10C emit: note: "CREATE 进入异步执行中" E40C: stage: sync_execute desc: "CREATE 执行结果回写:进行中/成功/失败" from: [S10C] outcomes: - when: { handler_result: SUCCESS } to: S11C emit: note: "CREATE 执行成功" - when: { handler_result: FAILED } to: S12C emit: note: "CREATE 执行失败" E40U_START: stage: sync_execute desc: "UPDATE 执行入口:进入异步执行中" from: [S07] outcomes: - when: { handler_result: IN_PROGRESS } to: S10U emit: note: "UPDATE 进入异步执行中" E40U: stage: sync_execute desc: "UPDATE 执行结果回写:进行中/成功/失败/跳过" from: [S10U] outcomes: - when: { handler_result: SUCCESS } to: S11U emit: note: "UPDATE 执行成功" - when: { handler_result: FAILED } to: S12U emit: note: "UPDATE 执行失败" - when: { handler_result: SKIPPED } to: S14 emit: note: "更新降级并跳过" E40D_START: stage: sync_execute desc: "DELETE 执行入口:进入异步执行中" from: [S09] outcomes: - when: { handler_result: IN_PROGRESS } to: S10D emit: note: "DELETE 进入异步执行中" E40D: stage: sync_execute desc: "DELETE 执行结果回写:进行中/成功/失败" from: [S10D] outcomes: - when: { handler_result: SUCCESS } to: S11D emit: note: "DELETE 执行成功" delete_node: true - when: { handler_result: FAILED } to: S12D emit: note: "DELETE 执行失败" invariants: INV-1_UNCHECKED_ACTION_NONE: desc: "UNCHECKED 不允许有动作" when: { binding_status: UNCHECKED } require: { action: NONE } INV-2_BLOCKING_NO_ACTION: desc: "阻断态不允许执行动作" when_any: - { binding_status: ABNORMAL } - { binding_status: WARNING } - { binding_status: DEPENDENCY_ERROR } require: { action: NONE } INV-3_PRECOND_IMPLIES_UPDATE: desc: "PRECONDITION_FAILED 必须伴随 action=UPDATE" when: { status: PRECONDITION_FAILED } require: { action: UPDATE }