{
 "ticket": "U89 #126",
 "startedAt": "2026-10-28T12:38:51.758122+08:00",
 "finishedAt": "2026-10-28T12:39:51.161189+08:00",
 "input": "python3 labs/iot-command/run.py",
 "exitCode": 0,
 "environment": {
  "jdk": "openjdk version \"21.0.11\" 2026-04-21 LTS\nOpenJDK Runtime Environment (build 21.0.11+11-LTS)\nOpenJDK 64-Bit Server VM (build 21.0.11+11-LTS, mixed mode, sharing)",
  "maven": "Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937)\nMaven home: /Users/gaochao/develop/maven-3.9.9\nJava version: 21.0.11, vendor: BellSoft, runtime: /Library/Java/JavaVirtualMachines/liberica-jdk-21.jdk/Contents/Home\nDefault locale: zh_CN_#Hans, platform encoding: UTF-8\nOS name: \"mac os x\", version: \"27.2\", arch: \"aarch64\", family: \"mac\"",
  "os": "macOS-27.2-arm64-arm-64bit",
  "arch": "arm64",
  "python": "3.9.6",
  "broker": "HiveMQ Community Edition 2026.5（嵌入式，真实 Netty MQTT 监听器与文件持久化）",
  "client": "HiveMQ MQTT Client 1.4.1（MQTT 5）与 device_client.py（Python 标准库独立实现）",
  "dependencies": {
   "hivemq-community-edition-embedded": "2026.5",
   "netty-handler": "4.1.134.Final",
   "hivemq-extension-sdk": "4.52.0",
   "hivemq-mqtt-client": "1.4.1",
   "jackson-databind": "2.21.7",
   "jackson-annotations": "2.21",
   "jackson-core": "2.21.7"
  }
 },
 "reports": [
  {
   "name": "study.iot.command.CommandShadowTest",
   "tests": "13",
   "failures": "0",
   "errors": "0",
   "skipped": "0"
  },
  {
   "name": "study.iot.command.EndToEndCommandTest",
   "tests": "2",
   "failures": "0",
   "errors": "0",
   "skipped": "0"
  }
 ],
 "testCount": 15,
 "results": [
  {
   "name": "jdk",
   "command": [
    "/Library/Java/JavaVirtualMachines/liberica-jdk-21.jdk/Contents/Home/bin/java",
    "-version"
   ],
   "exitCode": 0,
   "runnerExitCode": 0,
   "timedOut": false,
   "failure": null,
   "cleanupError": null,
   "observed": []
  },
  {
   "name": "maven",
   "command": [
    "/Users/gaochao/develop/maven-3.9.9/bin/mvn",
    "-version"
   ],
   "exitCode": 0,
   "runnerExitCode": 0,
   "timedOut": false,
   "failure": null,
   "cleanupError": null,
   "observed": []
  },
  {
   "name": "test-iot-command",
   "command": [
    "/Users/gaochao/develop/maven-3.9.9/bin/mvn",
    "-B",
    "-ntp",
    "-q",
    "clean",
    "test"
   ],
   "exitCode": 0,
   "runnerExitCode": 0,
   "timedOut": false,
   "failure": null,
   "cleanupError": null,
   "observed": [
    "U89 shadowJson=PASS version=2 delta={speed=3}",
    "U89 shadowConflict=PASS version=2 desired={speed=5}",
    "U89 shadowDelete=PASS version=2 deleted=true",
    "U89 crossLanguage=PASS digest=c8361ce8e82298ef... createdAtUtc=2026-10-28T00:00:00.000Z",
    "U89 shadowMerge=PASS desired={speed=5, mode=auto} version=2",
    "U89 duplicate=PASS duplicateOutcome=DUPLICATE_SUCCEEDED effects=[c-dup]",
    "U89 lifecycle=PASS state=SUCCEEDED effects=[c-1] version=2 delta=0",
    "U89 offlineQueue=PASS messages={\"commandId\":\"c-old\"},{\"commandId\":\"c-new\"}",
    "U89 expired=PASS state=EXPIRED effects=[]",
    "U89 malformedRejected=PASS java=missing expireAt python={\"error\": \"missing required field expireAt\", \"ok\": false}",
    "U89 lateAck=PASS state=EXPIRED effects=[]",
    "U89 pythonAck=PASS commandId=c-ack success=true",
    "U89 duplicateInFlight=PASS outcome=DUPLICATE_IN_FLIGHT effects=[]",
    "U89 e2eOffline=PASS old=EXPIRED new=SUCCEEDED effects=[cmd-new]",
    "U89 e2e=PASS commandId=cmd-e2e-1 shadowVersion=2 delta=0 effects=[cmd-e2e-1]"
   ]
  },
  {
   "name": "dependency",
   "command": [
    "/Users/gaochao/develop/maven-3.9.9/bin/mvn",
    "-B",
    "-ntp",
    "-q",
    "dependency:list",
    "-DoutputFile=/dev/stdout"
   ],
   "exitCode": 0,
   "runnerExitCode": 0,
   "timedOut": false,
   "failure": null,
   "cleanupError": null,
   "observed": []
  }
 ],
 "artifacts": {
  "pom.xml": "74af071fbd54ed93386649deec7582eb25d88e85add996d76608335c7e6dfe58",
  "run.py": "c061dc426a5c205e44e8647e7fb235c335ff39abbb2b4b91b9a69445b06ec8f3",
  "README.md": "2a64026c0cc1388d6187cd59cf91f44f7217dd967c45279c793f6b0c14ced67f",
  "device_client.py": "57d4cc1a2b104af4a37320a8f3d894b29c2fcc0c4f142df6c12886b4e1aad40b",
  "src/main/java/study/iot/command/Command.java": "e4d7aa69953fb6f102a3e0a4240f199e36cffcff2372036ba7283891abb4ed8f",
  "src/main/java/study/iot/command/CommandService.java": "98e8a9950aca624e1402eaf9f7f570037a78357086b7bc4982cfe7c79e6c3451",
  "src/main/java/study/iot/command/Contract.java": "b97cea44b82ed11f87848374222440ae22ce25beb4b579729e2f29576d593006",
  "src/main/java/study/iot/command/EffectLog.java": "9667b84630e2b9350dfee6aa408c39bf6285353184362b3269bf44d01942b6ff",
  "src/main/java/study/iot/command/Shadow.java": "1e8afe476d2beabb577ac6796b4374e5cd8dace19ed18a03dbae3711ebcfb095",
  "src/test/java/study/iot/command/CommandShadowTest.java": "e91689aba0360ec10ce3a7e1a576727da3ed45531fa1c9faaa54f4ceb5136577",
  "src/test/java/study/iot/command/EndToEndCommandTest.java": "e61e9f3b9a8b3dbb2f05e12bf27225bb6d88098445a81e4c0ea21c1958c2d67a",
  "src/test/java/study/iot/command/support/DeviceSecurityMain.java": "9a65ea03edec6237a69f83aa0300f93531db5de8f495a80cd80fe31b1fa8312c",
  "src/test/java/study/iot/command/support/ShadowBroker.java": "52454eb2e47655f3dfed55963bf4be8f40f601303f8f1278b72d2db60dbc0c37",
  "src/test/resources/logback.xml": "a8bb4449bd3808cf0ce97d43faf4c6a975ee3ed61d1d3d527a83d1884360299e"
 },
 "logs": "/Users/gaochao/.cache/software-engineering-study/java-depth-impl/u89/run-0qvtpsyf",
 "cleanup": {
  "processes": "本入口创建的进程组已回收；每个用例的 EmbeddedHiveMQ 在 finally 中 stop+close，临时数据目录删除",
  "externalServices": "无外部服务；broker 监听 127.0.0.1 随机端口，仅使用临时目录与合成数据"
 },
 "limits": [
  "影子与命令状态机是单进程 Java 教学实现，效果写本地文件；未接入生产数据库事务、多节点命令服务或真实云 IoT 平台影子",
  "跨语言客户端为 Python 标准库实现，只覆盖契约的编解码与摘要一致性，不含固件 C/C++ 或 C# 实现",
  "TLS/mTLS、增强认证、WebSocket、外部凭据源与 broker 集群/桥接未运行",
  "时间过期用可控 Clock 制造，不是真实等待数分钟；断线恢复是正常 disconnect 后重连，不是 kill -9/断电",
  "未做容量与并发压测；两路并发更新影子按顺序模拟，不是真实多线程争用"
 ]
}
