{ "title": "实装人工事件与红蓝对抗正式 API 闭环", "status": "PASS", "startedAt": "2026-09-05T15:48:46.342Z", "baseURL": "http://127.0.0.1:6180", "method": "真实 Auth / Gateway / Tran API;新建隔离学生与开发测试任务;不连接设备、视觉推理或外部通知。", "references": { "PHYSICAL": { "projectId": "163", "versionId": "215" }, "CONFRONTATION": { "projectId": "164", "versionId": "216" } }, "checks": [ { "title": "开始命令重放不会重复激活或递增次数", "status": "PASS", "details": { "runId": "44", "version": 2, "attemptCount": 1 } }, { "title": "实装任务固定发布版本、分配学员并开始", "status": "PASS", "details": { "assignmentId": "50", "run": { "id": "44", "assignmentId": "50", "status": "IN_PROGRESS", "version": 2, "progressPercent": 0, "currentStepCode": "PHYSICAL-S01", "score": null, "passed": null }, "content": { "projectId": "163", "versionId": "215" }, "rules": [ { "stepCode": "PHYSICAL-S01", "source": "MANUAL", "eventType": "step.physical-s01.confirmed", "progressPercent": 33 }, { "stepCode": "PHYSICAL-S02", "source": "MANUAL", "eventType": "step.physical-s02.confirmed", "progressPercent": 67 }, { "stepCode": "PHYSICAL-S03", "source": "MANUAL", "eventType": "step.physical-s03.confirmed", "progressPercent": 100 } ] } }, { "title": "实装拒绝普通进度接口、抢跑、提前提交及错误事件身份", "status": "PASS", "details": { "runId": "44", "forbiddenProgress": { "status": 403, "message": "实装运行只能由设备、视觉或人工确认事件推进" }, "prematureSubmit": { "status": 409, "message": "训练步骤尚未全部完成,不能提交" }, "skipped": { "status": 409, "message": "物理事件必须匹配当前待完成步骤,不能跳步或回退" }, "untrustedDevice": { "status": 403, "message": "无权执行此操作" }, "managerManual": { "status": 403, "message": "当前学员不是该运行成员" }, "progressUnchanged": 0 } }, { "title": "实装不匹配事件失败,必须重试后才可继续", "status": "PASS", "details": { "runId": "44", "outcome": "UNMATCHED", "beforeRetry": { "status": 409, "message": "实装步骤失败后必须先重试,完成后不能再次推进" }, "facts": [ { "stepCode": "PHYSICAL-S01", "status": "IN_PROGRESS", "targetProgressPercent": 33, "attemptCount": 2, "failureCount": 1, "evidenceSourceCode": "COMMAND" }, { "stepCode": "PHYSICAL-S02", "status": "PENDING", "targetProgressPercent": 67, "attemptCount": 0, "failureCount": 0, "evidenceSourceCode": "NONE" }, { "stepCode": "PHYSICAL-S03", "status": "PENDING", "targetProgressPercent": 100, "attemptCount": 0, "failureCount": 0, "evidenceSourceCode": "NONE" } ] } }, { "title": "实装逐步人工确认、事件幂等与载荷冲突", "status": "PASS", "details": { "runId": "44", "progression": [ { "stepCode": "PHYSICAL-S01", "eventId": "MANUAL-FF103EF3-B498-4EAC-8F06-42DE46CC9CE4", "progress": 33, "replayVersion": 5, "alteredEventStatus": 409 }, { "stepCode": "PHYSICAL-S02", "eventId": "MANUAL-9D8A36B7-C161-4736-A71E-D1700E55216B", "progress": 67, "replayVersion": 6, "alteredEventStatus": 409 }, { "stepCode": "PHYSICAL-S03", "eventId": "MANUAL-1D1ADE8F-D32B-434B-A7D8-A2571E502137", "progress": 100, "replayVersion": 7, "alteredEventStatus": 409 } ], "facts": [ { "stepCode": "PHYSICAL-S01", "status": "COMPLETED", "targetProgressPercent": 33, "attemptCount": 2, "failureCount": 1, "evidenceSourceCode": "MANUAL" }, { "stepCode": "PHYSICAL-S02", "status": "COMPLETED", "targetProgressPercent": 67, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "MANUAL" }, { "stepCode": "PHYSICAL-S03", "status": "COMPLETED", "targetProgressPercent": 100, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "MANUAL" } ] } }, { "title": "PHYSICAL 提交、教员评定与结果回读", "status": "PASS", "details": { "run": { "id": "44", "assignmentId": "50", "status": "REVIEWED", "version": 9, "progressPercent": 100, "currentStepCode": "PHYSICAL-S03", "score": 100, "passed": true }, "submitReplay": true, "reviewReplay": true, "facts": [ { "stepCode": "PHYSICAL-S01", "status": "COMPLETED", "targetProgressPercent": 33, "attemptCount": 2, "failureCount": 1, "evidenceSourceCode": "MANUAL" }, { "stepCode": "PHYSICAL-S02", "status": "COMPLETED", "targetProgressPercent": 67, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "MANUAL" }, { "stepCode": "PHYSICAL-S03", "status": "COMPLETED", "targetProgressPercent": 100, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "MANUAL" } ] } }, { "title": "对抗红蓝两队各两人,按队伍共享且运行互相独立", "status": "PASS", "details": { "assignmentId": "51", "content": { "projectId": "164", "versionId": "216" }, "configuration": { "teamSize": 2, "roundDurationMinutes": 7, "submitPositions": [ "COMMANDER" ] }, "runs": [ { "id": "46", "assignmentId": "51", "status": "ACCEPTED", "version": 1, "progressPercent": 0, "currentStepCode": "", "score": null, "passed": null }, { "id": "45", "assignmentId": "51", "status": "ACCEPTED", "version": 1, "progressPercent": 0, "currentStepCode": "", "score": null, "passed": null } ] } }, { "title": "对抗学员不能读取另一队运行明细", "status": "PASS", "details": { "requestingTeam": "RED", "otherRunId": "46", "response": { "status": 403, "message": "无权查看该训练运行" } } }, { "title": "开始命令重放不会重复激活或递增次数", "status": "PASS", "details": { "runId": "45", "version": 2, "attemptCount": 1 } }, { "title": "RED 队岗位越权、跳步和提前提交均拒绝", "status": "PASS", "details": { "runId": "45", "wrongPosition": { "status": 403, "message": "当前岗位不能推进共享训练进度" }, "skipped": { "status": 400, "message": "必须按发布顺序完成当前步骤,不能跳步或回退" }, "earlySubmit": { "status": 409, "message": "训练步骤尚未全部完成,不能提交" }, "deadlineAt": 1788623936, "serverNow": 1788623517 } }, { "title": "RED 队授权动作逐步推进、重放幂等、提交负责人限制", "status": "PASS", "details": { "runId": "45", "progression": [ { "stepCode": "CONFRONTATION-S01", "progress": 50, "replayVersion": 3, "changedCommandStatus": 409 }, { "stepCode": "CONFRONTATION-S02", "progress": 100, "replayVersion": 4, "changedCommandStatus": 409 } ], "wrongSubmitPosition": { "status": 403, "message": "共享训练仅允许任务声明的负责人岗位提交结果" } } }, { "title": "CONFRONTATION 提交、教员评定与结果回读", "status": "PASS", "details": { "run": { "id": "45", "assignmentId": "51", "status": "REVIEWED", "version": 6, "progressPercent": 100, "currentStepCode": "CONFRONTATION-S02", "score": 100, "passed": true }, "submitReplay": true, "reviewReplay": true, "facts": [ { "stepCode": "CONFRONTATION-S01", "status": "COMPLETED", "targetProgressPercent": 50, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "COMMAND" }, { "stepCode": "CONFRONTATION-S02", "status": "COMPLETED", "targetProgressPercent": 100, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "COMMAND" } ] } }, { "title": "红队完成不会推进蓝队进度", "status": "PASS", "details": { "redRunId": "45", "blueRun": { "id": "46", "assignmentId": "51", "status": "ACCEPTED", "version": 1, "progressPercent": 0, "currentStepCode": "", "score": null, "passed": null } } }, { "title": "开始命令重放不会重复激活或递增次数", "status": "PASS", "details": { "runId": "46", "version": 2, "attemptCount": 1 } }, { "title": "BLUE 队岗位越权、跳步和提前提交均拒绝", "status": "PASS", "details": { "runId": "46", "wrongPosition": { "status": 403, "message": "当前岗位不能推进共享训练进度" }, "skipped": { "status": 400, "message": "必须按发布顺序完成当前步骤,不能跳步或回退" }, "earlySubmit": { "status": 409, "message": "训练步骤尚未全部完成,不能提交" }, "deadlineAt": 1788623942, "serverNow": 1788623523 } }, { "title": "BLUE 队授权动作逐步推进、重放幂等、提交负责人限制", "status": "PASS", "details": { "runId": "46", "progression": [ { "stepCode": "CONFRONTATION-S01", "progress": 50, "replayVersion": 3, "changedCommandStatus": 409 }, { "stepCode": "CONFRONTATION-S02", "progress": 100, "replayVersion": 4, "changedCommandStatus": 409 } ], "wrongSubmitPosition": { "status": 403, "message": "共享训练仅允许任务声明的负责人岗位提交结果" } } }, { "title": "CONFRONTATION 提交、教员评定与结果回读", "status": "PASS", "details": { "run": { "id": "46", "assignmentId": "51", "status": "REVIEWED", "version": 6, "progressPercent": 100, "currentStepCode": "CONFRONTATION-S02", "score": 100, "passed": true }, "submitReplay": true, "reviewReplay": true, "facts": [ { "stepCode": "CONFRONTATION-S01", "status": "COMPLETED", "targetProgressPercent": 50, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "COMMAND" }, { "stepCode": "CONFRONTATION-S02", "status": "COMPLETED", "targetProgressPercent": 100, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "COMMAND" } ] } }, { "title": "正式任务快照固定训练、场景与模型发布版本", "status": "PASS", "details": { "snapshots": [ { "assignmentId": "50", "channel": "PHYSICAL", "content": { "projectId": "163", "versionId": "215" }, "frozenScene": { "projectId": "159", "versionId": "209", "models": [ { "projectId": "156", "versionId": "204", "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK" } ] } }, { "assignmentId": "51", "channel": "CONFRONTATION", "content": { "projectId": "164", "versionId": "216" }, "frozenScene": { "projectId": "160", "versionId": "210", "models": [ { "projectId": "157", "versionId": "201", "assetCode": "MODEL_MTO6V5W6_09-FOX" } ] } } ] } } ], "assignments": [ { "id": "50", "code": "UTE2E-MODES-MTOK5BBA-PHYSICAL", "channel": "PHYSICAL", "contentProjectId": "163", "contentVersionId": "215", "status": "PUBLISHED", "version": 1, "frozenScene": { "projectId": "159", "versionId": "209", "models": [ { "projectId": "156", "versionId": "204", "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK" } ] } }, { "id": "51", "code": "UTE2E-MODES-MTOK5BBA-CONFRONTATION", "channel": "CONFRONTATION", "contentProjectId": "164", "contentVersionId": "216", "status": "PUBLISHED", "version": 1, "frozenScene": { "projectId": "160", "versionId": "210", "models": [ { "projectId": "157", "versionId": "201", "assetCode": "MODEL_MTO6V5W6_09-FOX" } ] } } ], "runs": [ { "id": "44", "assignmentId": "50", "status": "REVIEWED", "version": 9, "progressPercent": 100, "currentStepCode": "PHYSICAL-S03", "score": 100, "passed": true, "channel": "PHYSICAL", "team": "NEUTRAL", "stepFacts": [ { "stepCode": "PHYSICAL-S01", "status": "COMPLETED", "targetProgressPercent": 33, "attemptCount": 2, "failureCount": 1, "evidenceSourceCode": "MANUAL" }, { "stepCode": "PHYSICAL-S02", "status": "COMPLETED", "targetProgressPercent": 67, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "MANUAL" }, { "stepCode": "PHYSICAL-S03", "status": "COMPLETED", "targetProgressPercent": 100, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "MANUAL" } ] }, { "id": "45", "assignmentId": "51", "status": "REVIEWED", "version": 6, "progressPercent": 100, "currentStepCode": "CONFRONTATION-S02", "score": 100, "passed": true, "channel": "CONFRONTATION", "team": "RED", "stepFacts": [ { "stepCode": "CONFRONTATION-S01", "status": "COMPLETED", "targetProgressPercent": 50, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "COMMAND" }, { "stepCode": "CONFRONTATION-S02", "status": "COMPLETED", "targetProgressPercent": 100, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "COMMAND" } ] }, { "id": "46", "assignmentId": "51", "status": "REVIEWED", "version": 6, "progressPercent": 100, "currentStepCode": "CONFRONTATION-S02", "score": 100, "passed": true, "channel": "CONFRONTATION", "team": "BLUE", "stepFacts": [ { "stepCode": "CONFRONTATION-S01", "status": "COMPLETED", "targetProgressPercent": 50, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "COMMAND" }, { "stepCode": "CONFRONTATION-S02", "status": "COMPLETED", "targetProgressPercent": 100, "attemptCount": 1, "failureCount": 0, "evidenceSourceCode": "COMMAND" } ] } ], "actors": [ { "userId": "95", "team": "RED", "position": "COMMANDER", "departmentId": "5" }, { "userId": "96", "team": "RED", "position": "OPERATOR", "departmentId": "5" }, { "userId": "97", "team": "BLUE", "position": "COMMANDER", "departmentId": "5" }, { "userId": "98", "team": "BLUE", "position": "OPERATOR", "departmentId": "5" } ], "requests": [ { "method": "POST", "path": "/api/tran/v1/teaching/assignments", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/assignments/50/publish", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/assignments/50/accept", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/start", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/start", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44/steps", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/44/progress", "status": 403 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/submit", "status": 409 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 409 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 403 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 403 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44/steps", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 409 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/start", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44/steps", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 409 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 409 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/physical-events", "status": 409 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44/steps", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/submit", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/submit", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/review", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/44/review", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/44/steps", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/assignments", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/assignments/51/publish", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/assignments/51/accept", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/assignments/51/accept", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/assignments/51/accept", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/assignments/51/accept", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs?assignmentId=51&size=100", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/46", "status": 403 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/45/start", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/45/start", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/45/steps", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/45/execution", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/45/progress", "status": 403 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/45/progress", "status": 400 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/45/submit", "status": 409 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/45", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/45/progress", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/45/progress", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/45/progress", "status": 409 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/45/progress", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/45/progress", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/45/progress", "status": 409 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/45/submit", "status": 403 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/45/submit", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/45/submit", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/45/review", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/45/review", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/45/steps", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/46", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/46/start", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/46/start", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/46/steps", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/46/execution", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/46/progress", "status": 403 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/46/progress", "status": 400 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/46/submit", "status": 409 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/46", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/46/progress", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/46/progress", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/46/progress", "status": 409 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/46/progress", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/46/progress", "status": 200 }, { "method": "PUT", "path": "/api/tran/v1/teaching/runs/46/progress", "status": 409 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/46/submit", "status": 403 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/46/submit", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/46/submit", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/46/review", "status": 200 }, { "method": "POST", "path": "/api/tran/v1/teaching/runs/46/review", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/runs/46/steps", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/assignments/50", "status": 200 }, { "method": "GET", "path": "/api/tran/v1/teaching/assignments/51", "status": 200 } ], "limitations": [ "实装事件均为本次自动化提交的 MANUAL 人工确认或明确的权限拒绝测试,不代表真实设备、PLC、摄像机或视觉模型联调。", "教学运行结果来自正式 API;默认实装离线回放和默认对抗本地工作台的显示另行记录,不混同为服务端运行闭环。", "对抗按四名隔离学员的独立会话依次操作,检查服务端截止时间已生效;未等待整局自然超时,也不代表多人同时操作的压力或网络同步测试。", "测试账号使用本次随机密码,密码与会话仅在运行内存中;报告只保留用户 ID、队伍和岗位以便追溯。" ], "finishedAt": "2026-09-05T15:58:56.293Z", "retainedData": { "assignments": [ "50", "51" ], "runs": [ "44", "45", "46" ], "users": [ "95", "96", "97", "98" ], "note": "仅新建本次开发测试数据,未修改或删除既有账号、任务与运行。" } }