/** * v1.8.3 — wire-code-based 判据 + ErrorInfo phase?/step? optional (clean break) * * 修 v1.8.x cycle 长尾 wart: * - leaf 码 wire (SYNC/RATER/BARGRAPH SIMPLE + Cured-with-leaf-wire) 失败时 * 被迫塞 phase=UNKNOWN/step=UNKNOWN 占位, dashboard ⚠️ TOLERATED * - 协议方 reply #2 (Round 11''') ACCEPT 设备端 clean break push back: * leaf 路径 phase/step 必须缺失; orchestrator 路径 UNKNOWN 占位 REJECT * * ⚠️ commandType 陷阱红线: BATCH 子项 wire 的 command.commandType="SIMPLE", 但 wire data.code * 是 BATCH_*_FAILED orchestrator-coded. 任何 validator/派生/路由判据必须用 wire data.code, * 禁止用 command.commandType (见 protocol-team-reply-2-to-proposal-v1.8.3.md §2). * * 设计文档: * - Round 9''' protocol-team-reply-to-proposal-v1.8.3.md (ACCEPT 6 + open Sub-decision 3) * - Round 10''' device-team-final-ack-v1.8.3.md (6 ACCEPT + 1 PUSH BACK clean break) * - Round 11''' protocol-team-reply-2-to-proposal-v1.8.3.md (ACCEPT clean break, cycle CLOSED) * - 设备端 commit A+C+F (sg7-31-win 仓, 已 ship clean break wire 形态) */ import { isOrchestratorCodedWire } from '../index'; describe('v1.8.3 — isOrchestratorCodedWire (wire-code-based 判据)', () => { describe('1. orchestrator-coded wire prefix (返回 true, phase/step 必填)', () => { test('BATCH 三态 + 子项 → true (BATCH_EXECUTE phase)', () => { expect(isOrchestratorCodedWire('BATCH_BARGRAPH_LED_SWITCH_WRITE_ALL_FAILED')).toBe(true); expect(isOrchestratorCodedWire('BATCH_BARGRAPH_LED_SWITCH_WRITE_FAILED')).toBe(true); expect(isOrchestratorCodedWire('BATCH_SYNC_FUNCTIONS_SWITCH_READ_PARTIAL_SUCCESS')).toBe(true); expect(isOrchestratorCodedWire('BATCH_BARGRAPH_LED_SWITCH_WRITE_BROADCAST_ALL_FAILED')).toBe(true); }); test('PROGRAM Upload 8 阶段 → true (PROGRAM_* phase)', () => { expect(isOrchestratorCodedWire('PROGRAM_INIT_FAILED')).toBe(true); expect(isOrchestratorCodedWire('PROGRAM_FETCH_FAILED')).toBe(true); expect(isOrchestratorCodedWire('PROGRAM_EXTRACT_FAILED')).toBe(true); expect(isOrchestratorCodedWire('PROGRAM_PREPROCESS_FAILED')).toBe(true); expect(isOrchestratorCodedWire('PROGRAM_COMPILE_FAILED')).toBe(true); expect(isOrchestratorCodedWire('PROGRAM_UPLOAD_FAILED')).toBe(true); expect(isOrchestratorCodedWire('PROGRAM_STATS_FAILED')).toBe(true); expect(isOrchestratorCodedWire('PROGRAM_COMPLETED')).toBe(true); expect(isOrchestratorCodedWire('PROGRAM_COMPLETE_FINAL')).toBe(true); // v1.10.0 §1 (镜像 QUICK_DETECTION_COMPLETE_FINAL) }); test('QuickDetection 7 阶段 → true (v1.9.0 QUICK_DETECTION_ 单 prefix)', () => { expect(isOrchestratorCodedWire('QUICK_DETECTION_INIT_FAILED')).toBe(true); expect(isOrchestratorCodedWire('QUICK_DETECTION_SWITCH_DETECT_FAILED')).toBe(true); expect(isOrchestratorCodedWire('QUICK_DETECTION_SWITCH_CONFIG_READ_FAILED')).toBe(true); expect(isOrchestratorCodedWire('QUICK_DETECTION_SWITCH_CONFIG_READ_COMM_BOARD_FAILED')).toBe(true); // §C expect(isOrchestratorCodedWire('QUICK_DETECTION_SYNC_DETECT_FAILED')).toBe(true); expect(isOrchestratorCodedWire('QUICK_DETECTION_BARGRAPH_DETECT_FAILED')).toBe(true); expect(isOrchestratorCodedWire('QUICK_DETECTION_SYNC_RECOVER_FAILED')).toBe(true); expect(isOrchestratorCodedWire('QUICK_DETECTION_COMPLETE_FAILED')).toBe(true); expect(isOrchestratorCodedWire('QUICK_DETECTION_COMPLETE_FINAL')).toBe(true); // §B }); test('SYNC_MONITORING_TABLE / SYNC_EXPORT → true (SYNC_EXPORT phase)', () => { expect(isOrchestratorCodedWire('SYNC_MONITORING_TABLE_EXPORT_FAILED')).toBe(true); expect(isOrchestratorCodedWire('SYNC_EXPORT_FAILED')).toBe(true); }); test('v1.9.0: BARGRAPH_CHECK_ONLINE_STATUS prefix 已删 → false (设备端 0 emit dead spec)', () => { // v1.8.5: 曾在 isOrchestratorCodedWire 第 5 prefix, 但设备端 0 emit (Cured 内部 routing 路径 30) // v1.9.0: 协议方删 prefix dead spec, 但设备端 C# CuredActionCode.BargraphCheckOnlineStatus=30 enum 保留 // (MEMORY rule #6 spec vs 内部 routing 解耦) expect(isOrchestratorCodedWire('BARGRAPH_CHECK_ONLINE_STATUS_FAILED')).toBe(false); }); test('Edge 自合成 EDGE_* → true (EDGE_PROXY phase)', () => { expect(isOrchestratorCodedWire('EDGE_COMMAND_REJECTED')).toBe(true); expect(isOrchestratorCodedWire('EDGE_CACHE_MISS')).toBe(true); }); }); describe('2. leaf 码 wire (返回 false, phase/step 必须缺失)', () => { test('SYNC SIMPLE 命令失败 → false', () => { expect(isOrchestratorCodedWire('SYNC_FUNCTIONS_SWITCH_READ_FAILED')).toBe(false); expect(isOrchestratorCodedWire('SYNC_STARTING_SPEED_LIMIT_SET_FAILED')).toBe(false); expect(isOrchestratorCodedWire('SYNC_PROGRAM_PUZZLE_READ_FAILED')).toBe(false); }); test('RATER SIMPLE 命令失败 → false', () => { expect(isOrchestratorCodedWire('RATER_FUNCTIONS_SWITCH_READ_FAILED')).toBe(false); }); test('BARGRAPH SIMPLE 命令失败 → false (BATCH_ prefix 才是 orchestrator)', () => { expect(isOrchestratorCodedWire('BARGRAPH_LED_SWITCH_WRITE_FAILED')).toBe(false); expect(isOrchestratorCodedWire('BARGRAPH_TRAIN_LENGTH_READ_FAILED')).toBe(false); expect(isOrchestratorCodedWire('BARGRAPH_MISALIGNMENT_READ_FAILED')).toBe(false); }); test('Cured-with-leaf-wire (设备端 Cured 多步, wire 仍 leaf) → false', () => { expect(isOrchestratorCodedWire('SYNC_STARTING_SPEED_LIMIT_SET_FAILED')).toBe(false); expect(isOrchestratorCodedWire('COMMUNICATION_BOARD_ETHERNET_SWITCH_READ_FAILED')).toBe(false); }); test('成功类 wire (无 _FAILED 后缀) → 同样按前缀判, 不是 orchestrator', () => { expect(isOrchestratorCodedWire('SYNC_FUNCTIONS_SWITCH_READ_SUCCESS')).toBe(false); expect(isOrchestratorCodedWire('BARGRAPH_LED_SWITCH_WRITE_SUCCESS')).toBe(false); }); }); describe('3. boundary cases (非法输入 → false, 不抛错)', () => { test('empty string → false', () => { expect(isOrchestratorCodedWire('')).toBe(false); }); test('undefined / null → false', () => { expect(isOrchestratorCodedWire(undefined)).toBe(false); expect(isOrchestratorCodedWire(null)).toBe(false); }); test('非 string 类型 → false', () => { expect(isOrchestratorCodedWire(123 as any)).toBe(false); expect(isOrchestratorCodedWire({} as any)).toBe(false); expect(isOrchestratorCodedWire([] as any)).toBe(false); }); test('类似 prefix 但不严格匹配 → false', () => { // BATCH 必须有 _ 分隔 expect(isOrchestratorCodedWire('BATCHED_OPERATION')).toBe(false); // PROGRAM 必须有特定子前缀 (8 阶段之一) expect(isOrchestratorCodedWire('PROGRAM_FOO_FAILED')).toBe(false); // 拼写错误 expect(isOrchestratorCodedWire('BARGAPH_LED_SWITCH_WRITE_FAILED')).toBe(false); }); }); describe('4. ⚠️ commandType 陷阱 — wire data.code 才是判据, 不是 caller frame', () => { test('BATCH 子项 wire (caller=BATCH 但子帧 command.commandType="SIMPLE") 按 BATCH_ prefix 判 → orchestrator', () => { // 设备端 audit 实证 (Round 8 ' v1.8.2 + Round 10''' v1.8.3 ack §3.1): // 子项 PROGRESS_UPDATE 的 command.commandType = "SIMPLE" (caller frame), // 但 wire data.code = "BATCH_*_FAILED" 含 BATCH_ 前缀. // 必须按 wire code 判, 否则 BATCH 子项会被误判为 leaf 走 relaxed, 协议契约失守. const wireCode = 'BATCH_BARGRAPH_LED_SWITCH_WRITE_FAILED'; expect(isOrchestratorCodedWire(wireCode)).toBe(true); }); test('Cured 多步内部, 但 wire 是 leaf (caller=Cured, wire=leaf) → leaf', () => { // SyncStartingSpeedLimitSet Cured 内部多步 (读 pixel + 计算 + 写 speed), // 但 wire data.code = "SYNC_STARTING_SPEED_LIMIT_SET_FAILED" 是 leaf. // 必须按 wire code 判, 不是按 caller multi-step 判. const wireCode = 'SYNC_STARTING_SPEED_LIMIT_SET_FAILED'; expect(isOrchestratorCodedWire(wireCode)).toBe(false); }); }); describe('5. 镜像同源约束 (与设备端 C# IsOrchestratorCodedWire 一致)', () => { test('与设备端 v1.9.0 升级 C# helper 6 类 prefix 完全同源', () => { // v1.9.0: 由 7 prefix 降到 6 prefix — // · 删 BARGRAPH_CHECK_ONLINE_STATUS prefix #5 (设备端 0 emit dead spec) // · detection 7 子族合并到单一 QUICK_DETECTION_ prefix #3 // 这条测试不验证设备端 C#, 仅断言协议方 npm export 的 6 类 prefix 与 // 设备端 Round 3 final ack §A C# helper 6 类 prefix 一致. const orchestratorSamples = [ 'BATCH_X_Y_Z', 'PROGRAM_INIT_FAILED', 'PROGRAM_COMPLETE_FAILED', 'QUICK_DETECTION_INIT_FAILED', 'QUICK_DETECTION_SWITCH_DETECT_FAILED', 'QUICK_DETECTION_SWITCH_CONFIG_READ_FAILED', 'QUICK_DETECTION_SWITCH_CONFIG_READ_COMM_BOARD_FAILED', // §C 'QUICK_DETECTION_SYNC_DETECT_FAILED', 'QUICK_DETECTION_BARGRAPH_DETECT_FAILED', 'QUICK_DETECTION_SYNC_RECOVER_FAILED', 'QUICK_DETECTION_COMPLETE_FAILED', 'QUICK_DETECTION_COMPLETE_FINAL', // §B 'SYNC_MONITORING_TABLE_EXPORT_FAILED', 'SYNC_EXPORT_AGGREGATE_FAILED', 'EDGE_COMMAND_REJECTED', ]; for (const code of orchestratorSamples) { expect(isOrchestratorCodedWire(code)).toBe(true); } }); test('leaf 码全 false', () => { const leafSamples = [ 'SYNC_FUNCTIONS_SWITCH_READ_FAILED', 'SYNC_STARTING_SPEED_LIMIT_SET_FAILED', 'RATER_FUNCTIONS_SWITCH_READ_FAILED', 'BARGRAPH_LED_SWITCH_WRITE_FAILED', 'BARGRAPH_TRAIN_LENGTH_READ_FAILED', 'BARGRAPH_MISALIGNMENT_READ_FAILED', 'BARGRAPH_PROGRAM_PLAY_IMMEDIATELY_WRITE_FAILED', 'COMMUNICATION_BOARD_ETHERNET_SWITCH_READ_FAILED', ]; for (const code of leafSamples) { expect(isOrchestratorCodedWire(code)).toBe(false); } }); }); });