| @@ -0,0 +1,328 @@ | |||
| { | |||
| "pass": true, | |||
| "checks": [ | |||
| { | |||
| "task": "88", | |||
| "step": 1, | |||
| "target": "bridge-engine", | |||
| "picked": { | |||
| "x": 1015.0000000000001, | |||
| "y": 535.7640349787625 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 1, | |||
| "check": "wrong tool rejected; Escape leaves poses and progress unchanged" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 1, | |||
| "target": "bridge-paper", | |||
| "picked": { | |||
| "x": 1189.9941977014037, | |||
| "y": 630.8778892474477 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 1, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 2, | |||
| "target": "bridge-tank-valve", | |||
| "picked": { | |||
| "x": 1224.3398889114299, | |||
| "y": 630.9457721389707 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 2, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "target": "bridge-inlet", | |||
| "picked": { | |||
| "x": 1307.2770099242337, | |||
| "y": 594.3731653154827 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "target": "bridge-inlet-bag", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 631.1324163541328 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "target": "bridge-outlet", | |||
| "picked": { | |||
| "x": 1249.5000000000002, | |||
| "y": 588.3872583739098 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "target": "bridge-outlet-bag", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 631.0649704261706 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "target": "bridge-pump-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749404882067 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "target": "bridge-pump-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749397374121 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "target": "bridge-pump-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749397019398 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "target": "bridge-pump-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749404527312 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-pump-bolt-1", | |||
| "bridge-pump-bolt-2", | |||
| "bridge-pump-bolt-3", | |||
| "bridge-pump-bolt-4", | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 5, | |||
| "target": "bridge-old-pump", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 632.3471269406336 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 5, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-pump-bolt-1", | |||
| "bridge-pump-bolt-2", | |||
| "bridge-pump-bolt-3", | |||
| "bridge-pump-bolt-4", | |||
| "bridge-old-pump", | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 6, | |||
| "target": "bridge-paper", | |||
| "picked": { | |||
| "x": 1194.435173166285, | |||
| "y": 630.874411952604 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 6, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-pump-bolt-1", | |||
| "bridge-pump-bolt-2", | |||
| "bridge-pump-bolt-3", | |||
| "bridge-pump-bolt-4", | |||
| "bridge-old-pump", | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 7, | |||
| "target": "bridge-gasket", | |||
| "picked": { | |||
| "x": 1249.4999999999995, | |||
| "y": 630.8883671945545 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 7, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-pump-bolt-1", | |||
| "bridge-pump-bolt-2", | |||
| "bridge-pump-bolt-3", | |||
| "bridge-pump-bolt-4", | |||
| "bridge-old-pump", | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-new-pump", | |||
| "picked": { | |||
| "x": 1248.2392765221184, | |||
| "y": 632.0568816050143 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-1", | |||
| "check": "preparation save preserves placed but untightened bolt" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-1", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-1", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.008000000000000007 | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749404882067 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-2", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-2", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.008000000000000007 | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749397374128 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-3", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-3", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.008000000000000007 | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-3", | |||
| "picked": { | |||
| "x": 1249.4999999999998, | |||
| "y": 630.97493970194 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-4", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-4", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.008000000000000007 | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "check": "503 preserves operation and retry succeeds" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749404527312 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-old-pump" | |||
| ] | |||
| } | |||
| ], | |||
| "errors": [] | |||
| } | |||
| @@ -0,0 +1,717 @@ | |||
| { | |||
| "pass": true, | |||
| "checks": [ | |||
| { | |||
| "task": "89", | |||
| "step": 1, | |||
| "check": "wrong tool rejected; Escape leaves poses and progress unchanged" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 1, | |||
| "target": "bridge-small-valve", | |||
| "picked": { | |||
| "x": 1249.5002412712608, | |||
| "y": 630.5777537222049 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 1, | |||
| "check": "physical tray occupancy", | |||
| "stored": [] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 2, | |||
| "target": "bridge-small-pipe", | |||
| "picked": { | |||
| "x": 1249.511343546854, | |||
| "y": 630.9243461613266 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 2, | |||
| "target": "bridge-small-bag", | |||
| "picked": { | |||
| "x": 1249.5237608216112, | |||
| "y": 630.9337561143501 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 2, | |||
| "check": "physical tray occupancy", | |||
| "stored": [] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5001445871621, | |||
| "y": 630.411293349843 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5001445868954, | |||
| "y": 630.4112923318257 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5001445869875, | |||
| "y": 630.4112922081891 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5001445868954, | |||
| "y": 630.411292331826 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-valve", | |||
| "picked": { | |||
| "x": 1231.7693228292756, | |||
| "y": 630.5777537222052 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 4, | |||
| "target": "bridge-small-plug-1", | |||
| "picked": { | |||
| "x": 1249.5225682175646, | |||
| "y": 630.8977809163484 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 4, | |||
| "target": "bridge-small-plug-2", | |||
| "picked": { | |||
| "x": 1249.5225682614525, | |||
| "y": 630.8977809578514 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 4, | |||
| "target": "bridge-small-seat", | |||
| "picked": { | |||
| "x": 1249.500207959537, | |||
| "y": 631.1276696400746 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 4, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 5, | |||
| "target": "bridge-large-valve", | |||
| "picked": { | |||
| "x": 1249.7245792955082, | |||
| "y": 630.4104969399293 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 5, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 6, | |||
| "target": "bridge-large-pipe", | |||
| "picked": { | |||
| "x": 1249.512111228889, | |||
| "y": 630.9254237627724 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 6, | |||
| "target": "bridge-large-bag", | |||
| "picked": { | |||
| "x": 1249.5238251595379, | |||
| "y": 630.9335875212079 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 6, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5150587800808, | |||
| "y": 630.4224344530943 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5150587486603, | |||
| "y": 630.4224337647446 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5150587601102, | |||
| "y": 630.4224337725875 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5150587800808, | |||
| "y": 630.4224344530957 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-valve", | |||
| "picked": { | |||
| "x": 1249.7245792955082, | |||
| "y": 630.4104969399293 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve", | |||
| "bridge-large-bolt-1", | |||
| "bridge-large-bolt-2", | |||
| "bridge-large-bolt-3", | |||
| "bridge-large-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 8, | |||
| "target": "bridge-large-plug-1", | |||
| "picked": { | |||
| "x": 1249.5186577262555, | |||
| "y": 630.9003322145043 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 8, | |||
| "target": "bridge-large-plug-2", | |||
| "picked": { | |||
| "x": 1249.5186577469094, | |||
| "y": 630.9003322338912 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 8, | |||
| "target": "bridge-large-seat", | |||
| "picked": { | |||
| "x": 1211.9594824120277, | |||
| "y": 631.0309038609222 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 8, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve", | |||
| "bridge-large-bolt-1", | |||
| "bridge-large-bolt-2", | |||
| "bridge-large-bolt-3", | |||
| "bridge-large-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-seat", | |||
| "picked": { | |||
| "x": 1211.9594824120277, | |||
| "y": 631.0309038609222 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-plug-1", | |||
| "check": "installed oil plug removed directly" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-plug-1", | |||
| "picked": { | |||
| "x": 1249.5186577262557, | |||
| "y": 630.9003322145035 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-plug-2", | |||
| "check": "installed oil plug removed directly" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-plug-2", | |||
| "picked": { | |||
| "x": 1249.5186577469103, | |||
| "y": 630.9003322338904 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve", | |||
| "bridge-large-bolt-1", | |||
| "bridge-large-bolt-2", | |||
| "bridge-large-bolt-3", | |||
| "bridge-large-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-small-valve", | |||
| "picked": { | |||
| "x": 1249.4145040500296, | |||
| "y": 631.0747989773504 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-1", | |||
| "check": "preparation save preserves placed but untightened bolt" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-1", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-1", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999936 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5150587800808, | |||
| "y": 630.4224344530952 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-2", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-2", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999936 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5150587486603, | |||
| "y": 630.4224337647445 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-3", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-3", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999936 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5150587601102, | |||
| "y": 630.4224337725873 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-4", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-4", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999936 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5150587800808, | |||
| "y": 630.4224344530957 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 11, | |||
| "target": "bridge-large-bag", | |||
| "picked": { | |||
| "x": 1249.5238251595379, | |||
| "y": 630.9335875212089 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 11, | |||
| "target": "bridge-large-pipe", | |||
| "picked": { | |||
| "x": 1249.5121112288894, | |||
| "y": 630.9254237627831 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 11, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "target": "bridge-large-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5278116770771, | |||
| "y": 630.2882305760778 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "target": "bridge-large-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5278116646073, | |||
| "y": 630.2882295301911 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "target": "bridge-large-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5278116846418, | |||
| "y": 630.2882295365889 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "target": "bridge-large-bolt-4", | |||
| "picked": { | |||
| "x": 1249.527811677077, | |||
| "y": 630.288230576079 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-seat", | |||
| "picked": { | |||
| "x": 1249.500207959537, | |||
| "y": 631.1276696400746 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-plug-1", | |||
| "check": "installed oil plug removed directly" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-plug-1", | |||
| "picked": { | |||
| "x": 1249.5225682175662, | |||
| "y": 630.8977809163456 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-plug-2", | |||
| "check": "installed oil plug removed directly" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-plug-2", | |||
| "picked": { | |||
| "x": 1249.5225682614544, | |||
| "y": 630.8977809578479 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-large-valve", | |||
| "picked": { | |||
| "x": 1248.6202008477849, | |||
| "y": 631.9159210458049 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-1", | |||
| "check": "preparation save preserves placed but untightened bolt" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-1", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-1", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999912 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5001445871621, | |||
| "y": 630.4112933498424 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-2", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-2", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999912 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5001445868954, | |||
| "y": 630.4112923318257 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-3", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-3", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999912 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-3", | |||
| "picked": { | |||
| "x": 1249.500144586988, | |||
| "y": 630.4112922081893 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-4", | |||
| "check": "bolt remains on workbench until clicked; click places only; tools unlock at hole" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-4", | |||
| "check": "bolt placed by click; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999912 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "check": "503 preserves operation and retry succeeds" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-4", | |||
| "picked": { | |||
| "x": 1249.500144586895, | |||
| "y": 630.4112923318269 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "check": "physical tray occupancy", | |||
| "stored": [] | |||
| } | |||
| ], | |||
| "errors": [] | |||
| } | |||
| @@ -0,0 +1,6 @@ | |||
| <!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>螺栓:工作台取件 → 孔位就位 → 扳手紧固</title> | |||
| <style>body{margin:0;background:#eef5f2;color:#173f37;font:16px/1.7 system-ui,"Microsoft YaHei",sans-serif}main{max-width:1380px;margin:auto;padding:24px}section,figure{background:white;border:1px solid #ccdfd7;border-radius:12px;padding:20px;margin:18px 0}img{width:100%;height:auto}.pair{display:grid;grid-template-columns:1fr 1fr;gap:14px}h1{line-height:1.4}a{color:#087b65}@media(max-width:900px){.pair{grid-template-columns:1fr}}</style> | |||
| <main><h1>螺栓:工作台取件 → 孔位就位 → 扳手紧固</h1><p>2026-09-25 · 本地 6180 / 6100 Gateway · 管理员教员预览 · 1440×900</p> | |||
| <section><p>进入回装子操作时,螺栓留在工作台,视角聚焦待取件。点击原螺栓后播放就位动画,随后使用扳手完成紧固。查看标签只聚焦,不移动零件;就位不计为紧固完成。每颗螺栓分别执行这三个阶段。</p><p>保存准备记录、紧固提交失败时保留已就位的状态;允许再次拖入扳手重试。油堵直接拆卸和第 14 步安装面的正面视角继续保留。</p></section> | |||
| <section><h2>验证结果</h2><p>007 从第 1 步走到第 8 步,008 从第 1 步走到第 14 步,覆盖全部 12 颗回装螺栓。使用真实模型点击、工具拖放及预览校验接口。检查取件前工具禁用、点击后仍未紧固、保存准备记录后位置保持、最后一颗螺栓提交失败后重试。相关 Node 测试及 pnpm run build 通过。没有创建学员成绩或测试任务。</p><ul><li>007:38 条检查通过,0 个页面脚本错误。<a href="../bridge-bolt-pick-20260925-007/result.json">JSON 记录</a></li><li>008:82 条检查通过,0 个页面脚本错误。<a href="../bridge-bolt-pick-20260925-008/result.json">JSON 记录</a></li></ul></section> | |||
| <section><h2>007 第 8 步 · 螺栓 1</h2><div class="pair"><figure><img src="../bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-1.png" alt="点击前:工作台取件,工具暂不可用"><figcaption>点击前:工作台取件,工具暂不可用</figcaption></figure><figure><img src="../bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-1.png" alt="点击后:安装孔位就位,等待扳手紧固"><figcaption>点击后:安装孔位就位,等待扳手紧固</figcaption></figure></div></section><section><h2>008 第 10 步 · 螺栓 2</h2><div class="pair"><figure><img src="../bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-2.png" alt="点击前:工作台取件,工具暂不可用"><figcaption>点击前:工作台取件,工具暂不可用</figcaption></figure><figure><img src="../bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-2.png" alt="点击后:安装孔位就位,等待扳手紧固"><figcaption>点击后:安装孔位就位,等待扳手紧固</figcaption></figure></div></section><section><h2>008 第 14 步 · 螺栓 3</h2><div class="pair"><figure><img src="../bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-3.png" alt="点击前:工作台取件,工具暂不可用"><figcaption>点击前:工作台取件,工具暂不可用</figcaption></figure><figure><img src="../bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-3.png" alt="点击后:安装孔位就位,等待扳手紧固"><figcaption>点击后:安装孔位就位,等待扳手紧固</figcaption></figure></div></section></main></html> | |||
| @@ -0,0 +1,394 @@ | |||
| { | |||
| "pass": true, | |||
| "checks": [ | |||
| { | |||
| "task": "88", | |||
| "step": 1, | |||
| "target": "bridge-engine", | |||
| "picked": { | |||
| "x": 1015.0000000000001, | |||
| "y": 535.7640349787625 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 1, | |||
| "check": "wrong tool rejected; Escape leaves poses and progress unchanged" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 1, | |||
| "target": "bridge-paper", | |||
| "picked": { | |||
| "x": 1189.9941977014037, | |||
| "y": 630.8778892474477 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 1, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 2, | |||
| "target": "bridge-tank-valve", | |||
| "picked": { | |||
| "x": 1224.3398889114299, | |||
| "y": 630.9457721389707 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 2, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "target": "bridge-inlet", | |||
| "picked": { | |||
| "x": 1307.2770099242337, | |||
| "y": 594.3731653154827 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "target": "bridge-inlet-bag", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 631.1324163541328 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "target": "bridge-outlet", | |||
| "picked": { | |||
| "x": 1249.5000000000002, | |||
| "y": 588.3872583739098 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "target": "bridge-outlet-bag", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 631.0649704261706 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 3, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "target": "bridge-pump-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749404882067 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "target": "bridge-pump-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749397374121 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "target": "bridge-pump-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749397019398 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "target": "bridge-pump-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749404527312 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 4, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-pump-bolt-1", | |||
| "bridge-pump-bolt-2", | |||
| "bridge-pump-bolt-3", | |||
| "bridge-pump-bolt-4", | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 5, | |||
| "target": "bridge-old-pump", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 632.3471269406336 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 5, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-pump-bolt-1", | |||
| "bridge-pump-bolt-2", | |||
| "bridge-pump-bolt-3", | |||
| "bridge-pump-bolt-4", | |||
| "bridge-old-pump", | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 6, | |||
| "target": "bridge-paper", | |||
| "picked": { | |||
| "x": 1194.435173166285, | |||
| "y": 630.874411952604 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 6, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-pump-bolt-1", | |||
| "bridge-pump-bolt-2", | |||
| "bridge-pump-bolt-3", | |||
| "bridge-pump-bolt-4", | |||
| "bridge-old-pump", | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 7, | |||
| "target": "bridge-gasket", | |||
| "picked": { | |||
| "x": 1249.4999999999995, | |||
| "y": 630.8883671945545 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 7, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-pump-bolt-1", | |||
| "bridge-pump-bolt-2", | |||
| "bridge-pump-bolt-3", | |||
| "bridge-pump-bolt-4", | |||
| "bridge-old-pump", | |||
| "bridge-new-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-new-pump", | |||
| "picked": { | |||
| "x": 1248.2392765221184, | |||
| "y": 632.0568816050143 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-1", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.008000000000000007 | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749404882067 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-2", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.008000000000000007 | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749397374128 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-3", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.008000000000000007 | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-3", | |||
| "picked": { | |||
| "x": 1249.4999999999998, | |||
| "y": 630.97493970194 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-4", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.008000000000000007 | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "check": "503 preserves operation and retry succeeds" | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "target": "bridge-pump-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9749404527312 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 8, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-old-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 9, | |||
| "target": "bridge-fill-cap", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 630.9172747235208 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 9, | |||
| "target": "bridge-fill-port", | |||
| "picked": { | |||
| "x": 1212.4431336221521, | |||
| "y": 630.9401402415141 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 9, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-old-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 10, | |||
| "target": "bridge-inlet-bag", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 631.132416354133 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 10, | |||
| "target": "bridge-inlet", | |||
| "picked": { | |||
| "x": 1307.2770099242337, | |||
| "y": 594.3731653154824 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 10, | |||
| "target": "bridge-outlet-bag", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 631.0649704261702 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 10, | |||
| "target": "bridge-outlet", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 588.3872583739098 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 10, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-old-pump" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 11, | |||
| "target": "bridge-engine", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 631.745172863328 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 11, | |||
| "target": "bridge-test-control", | |||
| "picked": { | |||
| "x": 1249.5, | |||
| "y": 631.148312317676 | |||
| } | |||
| }, | |||
| { | |||
| "task": "88", | |||
| "step": 11, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-old-pump" | |||
| ] | |||
| } | |||
| ], | |||
| "errors": [] | |||
| } | |||
| @@ -0,0 +1,723 @@ | |||
| { | |||
| "pass": true, | |||
| "checks": [ | |||
| { | |||
| "task": "89", | |||
| "step": 1, | |||
| "check": "wrong tool rejected; Escape leaves poses and progress unchanged" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 1, | |||
| "target": "bridge-small-valve", | |||
| "picked": { | |||
| "x": 1249.5002412712608, | |||
| "y": 630.5777537222049 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 1, | |||
| "check": "physical tray occupancy", | |||
| "stored": [] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 2, | |||
| "target": "bridge-small-pipe", | |||
| "picked": { | |||
| "x": 1249.511343546854, | |||
| "y": 630.9243461613266 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 2, | |||
| "target": "bridge-small-bag", | |||
| "picked": { | |||
| "x": 1249.5237608216112, | |||
| "y": 630.9337561143501 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 2, | |||
| "check": "physical tray occupancy", | |||
| "stored": [] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5001445871621, | |||
| "y": 630.411293349843 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5001445868954, | |||
| "y": 630.4112923318257 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5001445869875, | |||
| "y": 630.4112922081891 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5001445868954, | |||
| "y": 630.411292331826 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "target": "bridge-small-valve", | |||
| "picked": { | |||
| "x": 1231.7693228292756, | |||
| "y": 630.5777537222052 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 3, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 4, | |||
| "target": "bridge-small-plug-1", | |||
| "picked": { | |||
| "x": 1249.5225682175646, | |||
| "y": 630.8977809163484 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 4, | |||
| "target": "bridge-small-plug-2", | |||
| "picked": { | |||
| "x": 1249.5225682614525, | |||
| "y": 630.8977809578514 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 4, | |||
| "target": "bridge-small-seat", | |||
| "picked": { | |||
| "x": 1249.500207959537, | |||
| "y": 631.1276696400746 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 4, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 5, | |||
| "target": "bridge-large-valve", | |||
| "picked": { | |||
| "x": 1249.7245792955082, | |||
| "y": 630.4104969399293 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 5, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 6, | |||
| "target": "bridge-large-pipe", | |||
| "picked": { | |||
| "x": 1249.512111228889, | |||
| "y": 630.9254237627724 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 6, | |||
| "target": "bridge-large-bag", | |||
| "picked": { | |||
| "x": 1249.5238251595379, | |||
| "y": 630.9335875212079 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 6, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5150587800808, | |||
| "y": 630.4224344530943 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5150587486603, | |||
| "y": 630.4224337647446 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5150587601102, | |||
| "y": 630.4224337725875 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5150587800808, | |||
| "y": 630.4224344530957 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "target": "bridge-large-valve", | |||
| "picked": { | |||
| "x": 1249.7245792955082, | |||
| "y": 630.4104969399293 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 7, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve", | |||
| "bridge-large-bolt-1", | |||
| "bridge-large-bolt-2", | |||
| "bridge-large-bolt-3", | |||
| "bridge-large-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 8, | |||
| "target": "bridge-large-plug-1", | |||
| "picked": { | |||
| "x": 1249.5186577262555, | |||
| "y": 630.9003322145043 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 8, | |||
| "target": "bridge-large-plug-2", | |||
| "picked": { | |||
| "x": 1249.5186577469094, | |||
| "y": 630.9003322338912 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 8, | |||
| "target": "bridge-large-seat", | |||
| "picked": { | |||
| "x": 1211.9594824120277, | |||
| "y": 631.0309038609222 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 8, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve", | |||
| "bridge-large-bolt-1", | |||
| "bridge-large-bolt-2", | |||
| "bridge-large-bolt-3", | |||
| "bridge-large-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-seat", | |||
| "picked": { | |||
| "x": 1211.9594824120277, | |||
| "y": 631.0309038609222 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-plug-1", | |||
| "check": "installed oil plug removed directly" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-plug-1", | |||
| "picked": { | |||
| "x": 1249.5186577262557, | |||
| "y": 630.9003322145035 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-plug-2", | |||
| "check": "installed oil plug removed directly" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "target": "bridge-large-plug-2", | |||
| "picked": { | |||
| "x": 1249.5186577469103, | |||
| "y": 630.9003322338904 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 9, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-small-valve", | |||
| "bridge-large-bolt-1", | |||
| "bridge-large-bolt-2", | |||
| "bridge-large-bolt-3", | |||
| "bridge-large-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-small-valve", | |||
| "picked": { | |||
| "x": 1249.4145040500296, | |||
| "y": 631.0747989773504 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-1", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999936 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5150587800808, | |||
| "y": 630.4224344530952 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-2", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999936 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5150587486603, | |||
| "y": 630.4224337647445 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-3", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999936 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5150587601102, | |||
| "y": 630.4224337725873 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-4", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999936 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "target": "bridge-large-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5150587800808, | |||
| "y": 630.4224344530957 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 10, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 11, | |||
| "target": "bridge-large-bag", | |||
| "picked": { | |||
| "x": 1249.5238251595379, | |||
| "y": 630.9335875212089 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 11, | |||
| "target": "bridge-large-pipe", | |||
| "picked": { | |||
| "x": 1249.5121112288894, | |||
| "y": 630.9254237627831 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 11, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "target": "bridge-large-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5278116770771, | |||
| "y": 630.2882305760778 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "target": "bridge-large-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5278116646073, | |||
| "y": 630.2882295301911 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "target": "bridge-large-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5278116846418, | |||
| "y": 630.2882295365889 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "target": "bridge-large-bolt-4", | |||
| "picked": { | |||
| "x": 1249.527811677077, | |||
| "y": 630.288230576079 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 12, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-seat", | |||
| "picked": { | |||
| "x": 1249.500207959537, | |||
| "y": 631.1276696400746 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-plug-1", | |||
| "check": "installed oil plug removed directly" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-plug-1", | |||
| "picked": { | |||
| "x": 1249.5225682175662, | |||
| "y": 630.8977809163456 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-plug-2", | |||
| "check": "installed oil plug removed directly" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "target": "bridge-small-plug-2", | |||
| "picked": { | |||
| "x": 1249.5225682614544, | |||
| "y": 630.8977809578479 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 13, | |||
| "check": "physical tray occupancy", | |||
| "stored": [ | |||
| "bridge-small-bolt-1", | |||
| "bridge-small-bolt-2", | |||
| "bridge-small-bolt-3", | |||
| "bridge-small-bolt-4", | |||
| "bridge-large-valve" | |||
| ] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-large-valve", | |||
| "picked": { | |||
| "x": 1248.6202008477849, | |||
| "y": 631.9159210458049 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-1", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999912 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-1", | |||
| "picked": { | |||
| "x": 1249.5001445871621, | |||
| "y": 630.4112933498424 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-2", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999912 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5001445868954, | |||
| "y": 630.4112923318257 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-3", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999912 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-3", | |||
| "picked": { | |||
| "x": 1249.500144586988, | |||
| "y": 630.4112922081893 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-4", | |||
| "check": "bolt pre-positioned; tightening unconfirmed; front-facing camera", | |||
| "mountingDistance": 0.007999999999999912 | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "check": "503 preserves operation and retry succeeds" | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "target": "bridge-small-bolt-4", | |||
| "picked": { | |||
| "x": 1249.500144586895, | |||
| "y": 630.4112923318269 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 14, | |||
| "check": "physical tray occupancy", | |||
| "stored": [] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 15, | |||
| "target": "bridge-small-bag", | |||
| "picked": { | |||
| "x": 1249.5237608216166, | |||
| "y": 630.9337561143498 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 15, | |||
| "target": "bridge-small-pipe", | |||
| "picked": { | |||
| "x": 1249.511343546855, | |||
| "y": 630.9243461613277 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 15, | |||
| "check": "physical tray occupancy", | |||
| "stored": [] | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 16, | |||
| "target": "bridge-small-bolt-1", | |||
| "picked": { | |||
| "x": 1249.500215349077, | |||
| "y": 630.4769337608634 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 16, | |||
| "target": "bridge-small-bolt-2", | |||
| "picked": { | |||
| "x": 1249.5002153490705, | |||
| "y": 630.4769333144791 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 16, | |||
| "target": "bridge-small-bolt-3", | |||
| "picked": { | |||
| "x": 1249.5002153490998, | |||
| "y": 630.4769331522325 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 16, | |||
| "target": "bridge-small-bolt-4", | |||
| "picked": { | |||
| "x": 1249.5002153490705, | |||
| "y": 630.4769333144793 | |||
| } | |||
| }, | |||
| { | |||
| "task": "89", | |||
| "step": 16, | |||
| "check": "physical tray occupancy", | |||
| "stored": [] | |||
| } | |||
| ], | |||
| "errors": [] | |||
| } | |||
| @@ -0,0 +1,7 @@ | |||
| <!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>螺栓安装、油堵拆卸与平衡阀视角修正</title> | |||
| <style>body{margin:0;background:#eef5f2;color:#173f37;font:16px/1.75 system-ui,"Microsoft YaHei",sans-serif}main{max-width:1160px;margin:auto;padding:32px 24px}section,figure{background:white;border:1px solid #ccdfd7;border-radius:12px;padding:24px;margin:18px 0}img{width:100%;height:auto}a{color:#087b65}h1{line-height:1.4}figcaption{margin-top:12px}</style> | |||
| <main><h1>螺栓安装、油堵拆卸与平衡阀视角修正</h1><p>2026-09-25 · 本地 6180 → 6100 Gateway · 维护账号教员预览 · 真实鼠标点击、工具拖放和服务端预览校验。</p> | |||
| <section><h2>完成内容</h2><ul><li>007、008 回装螺栓时,先把当前螺栓从暂存台送到安装孔,再等待学员用扳手紧固。搬运不完成子操作,不生成紧固证据。</li><li>008 第 9、13 步的油堵直接点击或拖动取下;第 4、8 步封堵仍使用工具箱油堵。</li><li>008 两侧螺栓按真实安装面法线设置视角,互换后的阀体跟随目的安装面。被交换阀体遮住的螺栓仍可见、可拾取。</li><li>保存失败恢复到待紧固位置,允许再次使用工具;不改写已发布任务、步骤数量或评分规则。</li></ul></section> | |||
| <section><h2>验证</h2><p>相关 Node 自动测试、正式路由契约和前端生产构建通过。007、008 全流程使用正式页面与预览接口;模拟最后一颗安装螺栓保存失败并重试。未创建学员成绩或测试教学任务。</p><ul><li><a href="../bridge-installation-fixes-20260925-007/result.json">bridge-installation-fixes-20260925-007</a>:通过,44 条检查,0 个页面脚本错误。</li><li><a href="../bridge-installation-fixes-20260925-008/result.json">bridge-installation-fixes-20260925-008</a>:通过,80 条检查,0 个页面脚本错误。</li></ul></section> | |||
| <figure><img src="../bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-1.png" alt="007:新泵安装后的第一颗螺栓,已到孔位,等待拖入扳手。"><figcaption>007:新泵安装后的第一颗螺栓,已到孔位,等待拖入扳手。</figcaption></figure><figure><img src="../bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-2.png" alt="008 第 10 步:大腔螺栓在安装位置等待工具,暂存台上的其余零件保持原位。"><figcaption>008 第 10 步:大腔螺栓在安装位置等待工具,暂存台上的其余零件保持原位。</figcaption></figure><figure><img src="../bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-3.png" alt="008 第 14 步:第 3 颗小腔螺栓,从安装面正面观察。"><figcaption>008 第 14 步:第 3 颗小腔螺栓,从安装面正面观察。</figcaption></figure> | |||
| </main></html> | |||
| @@ -0,0 +1,19 @@ | |||
| import fs from 'node:fs'; | |||
| import assert from 'node:assert/strict'; | |||
| const dir='reports/bridge-bolt-pick-20260925'; | |||
| const results=['007','008'].map(script=>{ | |||
| const result=JSON.parse(fs.readFileSync(`${dir}-${script}/result.json`,'utf8')); | |||
| assert.equal(result.pass,true,script); | |||
| return {script,...result}; | |||
| }); | |||
| const figures=[['007','88',8,1],['008','89',10,2],['008','89',14,3]]; | |||
| for(const [script,id,step,bolt] of figures)for(const phase of ['pick','mount'])assert.ok(fs.existsSync(`${dir}-${script}/task-${id}-${phase}-step-${step}-bolt-${bolt}.png`)); | |||
| fs.mkdirSync(dir,{recursive:true}); | |||
| fs.writeFileSync(`${dir}/index.html`,`<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>螺栓:工作台取件 → 孔位就位 → 扳手紧固</title> | |||
| <style>body{margin:0;background:#eef5f2;color:#173f37;font:16px/1.7 system-ui,"Microsoft YaHei",sans-serif}main{max-width:1380px;margin:auto;padding:24px}section,figure{background:white;border:1px solid #ccdfd7;border-radius:12px;padding:20px;margin:18px 0}img{width:100%;height:auto}.pair{display:grid;grid-template-columns:1fr 1fr;gap:14px}h1{line-height:1.4}a{color:#087b65}@media(max-width:900px){.pair{grid-template-columns:1fr}}</style> | |||
| <main><h1>螺栓:工作台取件 → 孔位就位 → 扳手紧固</h1><p>2026-09-25 · 本地 6180 / 6100 Gateway · 管理员教员预览 · 1440×900</p> | |||
| <section><p>进入回装子操作时,螺栓留在工作台,视角聚焦待取件。点击原螺栓后播放就位动画,随后使用扳手完成紧固。查看标签只聚焦,不移动零件;就位不计为紧固完成。每颗螺栓分别执行这三个阶段。</p><p>保存准备记录、紧固提交失败时保留已就位的状态;允许再次拖入扳手重试。油堵直接拆卸和第 14 步安装面的正面视角继续保留。</p></section> | |||
| <section><h2>验证结果</h2><p>007 从第 1 步走到第 8 步,008 从第 1 步走到第 14 步,覆盖全部 12 颗回装螺栓。使用真实模型点击、工具拖放及预览校验接口。检查取件前工具禁用、点击后仍未紧固、保存准备记录后位置保持、最后一颗螺栓提交失败后重试。相关 Node 测试及 pnpm run build 通过。没有创建学员成绩或测试任务。</p><ul>${results.map(r=>`<li>${r.script}:${r.checks.length} 条检查通过,${r.errors.length} 个页面脚本错误。<a href="../bridge-bolt-pick-20260925-${r.script}/result.json">JSON 记录</a></li>`).join('')}</ul></section> | |||
| ${figures.map(([script,id,step,bolt])=>`<section><h2>${script} 第 ${step} 步 · 螺栓 ${bolt}</h2><div class="pair">${[['pick','点击前:工作台取件,工具暂不可用'],['mount','点击后:安装孔位就位,等待扳手紧固']].map(([phase,title])=>`<figure><img src="../bridge-bolt-pick-20260925-${script}/task-${id}-${phase}-step-${step}-bolt-${bolt}.png" alt="${title}"><figcaption>${title}</figcaption></figure>`).join('')}</div></section>`).join('')}</main></html>`); | |||
| console.log(`${dir}/index.html`); | |||
| @@ -0,0 +1,22 @@ | |||
| import fs from 'node:fs'; | |||
| import assert from 'node:assert/strict'; | |||
| const dir='reports/bridge-installation-fixes-20260925'; | |||
| const reports=['bridge-installation-fixes-20260925-007','bridge-installation-fixes-20260925-008']; | |||
| const results=reports.map(name=>({name,result:JSON.parse(fs.readFileSync(`reports/${name}/result.json`,'utf8'))})); | |||
| for(const {name,result} of results)assert.equal(result.pass,true,name); | |||
| fs.mkdirSync(dir,{recursive:true}); | |||
| const figures=[ | |||
| ['007','88',8,1,'007:新泵安装后的第一颗螺栓,已到孔位,等待拖入扳手。'], | |||
| ['008','89',10,2,'008 第 10 步:大腔螺栓在安装位置等待工具,暂存台上的其余零件保持原位。'], | |||
| ['008','89',14,3,'008 第 14 步:第 3 颗小腔螺栓,从安装面正面观察。'], | |||
| ]; | |||
| for(const [suffix,id,step,bolt] of figures)assert.ok(fs.existsSync(`reports/bridge-installation-fixes-20260925-${suffix}/task-${id}-mount-step-${step}-bolt-${bolt}.png`)); | |||
| fs.writeFileSync(`${dir}/index.html`,`<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>螺栓安装、油堵拆卸与平衡阀视角修正</title> | |||
| <style>body{margin:0;background:#eef5f2;color:#173f37;font:16px/1.75 system-ui,"Microsoft YaHei",sans-serif}main{max-width:1160px;margin:auto;padding:32px 24px}section,figure{background:white;border:1px solid #ccdfd7;border-radius:12px;padding:24px;margin:18px 0}img{width:100%;height:auto}a{color:#087b65}h1{line-height:1.4}figcaption{margin-top:12px}</style> | |||
| <main><h1>螺栓安装、油堵拆卸与平衡阀视角修正</h1><p>2026-09-25 · 本地 6180 → 6100 Gateway · 维护账号教员预览 · 真实鼠标点击、工具拖放和服务端预览校验。</p> | |||
| <section><h2>完成内容</h2><ul><li>007、008 回装螺栓时,先把当前螺栓从暂存台送到安装孔,再等待学员用扳手紧固。搬运不完成子操作,不生成紧固证据。</li><li>008 第 9、13 步的油堵直接点击或拖动取下;第 4、8 步封堵仍使用工具箱油堵。</li><li>008 两侧螺栓按真实安装面法线设置视角,互换后的阀体跟随目的安装面。被交换阀体遮住的螺栓仍可见、可拾取。</li><li>保存失败恢复到待紧固位置,允许再次使用工具;不改写已发布任务、步骤数量或评分规则。</li></ul></section> | |||
| <section><h2>验证</h2><p>相关 Node 自动测试、正式路由契约和前端生产构建通过。007、008 全流程使用正式页面与预览接口;模拟最后一颗安装螺栓保存失败并重试。未创建学员成绩或测试教学任务。</p><ul>${results.map(({name,result})=>`<li><a href="../${name}/result.json">${name}</a>:通过,${result.checks.length} 条检查,${result.errors.length} 个页面脚本错误。</li>`).join('')}</ul></section> | |||
| ${figures.map(([suffix,id,step,bolt,caption])=>`<figure><img src="../bridge-installation-fixes-20260925-${suffix}/task-${id}-mount-step-${step}-bolt-${bolt}.png" alt="${caption}"><figcaption>${caption}</figcaption></figure>`).join('')} | |||
| </main></html>`); | |||
| console.log(`${dir}/index.html`); | |||
| @@ -5,7 +5,7 @@ import {login,call} from './role-permissions-live.mjs'; | |||
| import {finalAcceptance} from './bridge-final-acceptance.mjs'; | |||
| const fullFlow=process.env.FULL_FLOW==='1'; | |||
| const dir=(fullFlow?'reports/bridge-final-acceptance-20260924':'reports/bridge-training-safety-20260924')+(process.env.REPORT_SUFFIX||'');fs.mkdirSync(dir,{recursive:true}); | |||
| const dir=process.env.REPORT_DIR||((fullFlow?'reports/bridge-final-acceptance-20260924':'reports/bridge-training-safety-20260924')+(process.env.REPORT_SUFFIX||''));fs.mkdirSync(dir,{recursive:true}); | |||
| const session=await login('root'),checks=[],errors=[]; | |||
| const browser=await chromium.launch({channel:'msedge',headless:true,args:['--enable-unsafe-swiftshader']}); | |||
| const page=await browser.newPage({viewport:{width:Number(process.env.WIDTH)||1440,height:Number(process.env.HEIGHT)||900}}); | |||
| @@ -24,8 +24,12 @@ await page.route(/\/src\/features\/virtual-training-legacy\/upstream\/views\/tra | |||
| } | |||
| const roots=(e.publishedContentRoot?.children||[]).map(root=>{let faded=0,opaque=0,changed=0;root.traverse(m=>{if(!m.isMesh||m.userData.trainingPickProxy)return;for(const mat of Array.isArray(m.material)?m.material:[m.material]){if(mat.opacity<.4)faded++;else opaque++;if(mat.opacity!==e.viewerMaterialBaseline.get(mat)?.opacity)changed++;}});return {name:root.name,environment:e.viewerEnvironmentRoots?.has(root),faded,opaque,changed};}); | |||
| const pose=[...e.parts].map(([id,o])=>({id,p:o.position.toArray(),q:o.quaternion.toArray(),visible:o.visible})); | |||
| const activeFront=obj?.userData.trainingInspectionFront,viewDirection=e.camera.position.clone().sub(e.controls.target).normalize(); | |||
| return {id,tool:e.bridgeTools?.profile,canonicalId:e.getActiveMechanismOperation()?.operation.targetId,step:e.session.stepIndex,operation:e.getActiveMechanismOperation()?.state.index,operationData:e.getActiveMechanismOperation()?.operation, | |||
| points,freePoints,box,complete:e.session.currentComplete,pending:e.bridgeOperationPending||e.serverCommitPending,tween:!!e.viewerCameraTween, | |||
| mountingDistance:obj?.userData.home?obj.getWorldPosition(new THREE.Vector3()).distanceTo(obj.parent.localToWorld(obj.userData.home.position.clone())):null, | |||
| frontAlignment:activeFront?activeFront.dot(viewDirection):null, | |||
| needsPlacement:e.bridgePartsWorkbench?.needsPlacement(), | |||
| completed:[...e.session.completed],introductionActive:!!e.introductionActive, | |||
| camera:e.camera.position.toArray(),target:e.controls.target.toArray(),floor:e.viewerTerrainSurface?.heightAt(e.camera.position.x,e.camera.position.z),roots,pose, | |||
| tray:e.bridgePartsWorkbench?.root?{position:e.bridgePartsWorkbench.root.position.toArray(),items:[...e.bridgePartsWorkbench.items.values()].map(item=>{const bounds=new THREE.Box3().setFromObject(item.part,true);return {id:item.id,stored:item.stored,number:item.number,uuid:item.part.uuid,position:item.part.position.toArray(),slot:item.position.toArray(),bottom:bounds.min.y,top:e.bridgePartsWorkbench.layout.position.y};})}:null, | |||
| @@ -87,6 +91,42 @@ try{ | |||
| const ops=step.action.mechanism.steps; | |||
| for(let j=0;j<ops.length;j++){ | |||
| await settle();let d=await snap();assert.equal(d.canonicalId,ops[j].targetId); | |||
| if(d.needsPlacement){ | |||
| const stored=d.tray.items.find(item=>item.id===d.id); | |||
| assert.equal(stored.stored,true,'installation starts with the bolt on the workbench'); | |||
| assert.ok(Math.hypot(...stored.position.map((v,k)=>v-stored.slot[k]))<.00001); | |||
| assert.equal(d.tool.trigger,'direct','first phase is picking the bolt, not using a wrench'); | |||
| await page.locator('[data-role="part-label"]').click();await settle();d=await snap(); | |||
| assert.equal(d.needsPlacement,true,'focusing alone must not move the bolt'); | |||
| assert.ok(d.points.length,'workbench bolt is clickable'); | |||
| if(process.env.CHECK_INSTALLATION==='1'){ | |||
| assert.equal(await page.locator('[data-bridge-tool]:enabled').count(),0,'tools unavailable until the bolt is placed'); | |||
| await page.screenshot({path:dir+'/task-'+id+'-pick-step-'+(i+1)+'-bolt-'+j+'.png'}); | |||
| } | |||
| await page.mouse.click(d.points[0].x,d.points[0].y);await settle();d=await snap(); | |||
| assert.equal(d.needsPlacement,false);assert.equal(d.operation,j,'picking never completes tightening'); | |||
| assert.equal(d.tool.trigger,'tool-drop','wrench is required after placing the bolt'); | |||
| if(process.env.CHECK_INSTALLATION==='1'&&j===1){ | |||
| await page.locator('[data-open-preparation]').click();await page.locator('[data-save-preparation]').click();await page.locator('[data-close-preparation]').click();await settle();d=await snap(); | |||
| assert.equal(d.needsPlacement,false,'preparation save retains picked placement'); | |||
| checks.push({task:id,step:i+1,target:d.id,check:'preparation save preserves placed but untightened bolt'}); | |||
| } | |||
| checks.push({task:id,step:i+1,target:d.id,check:'bolt remains on workbench until clicked; click places only; tools unlock at hole'}); | |||
| } | |||
| if(process.env.CHECK_INSTALLATION==='1'){ | |||
| const installation=(id==='88'&&i===7)||(id==='89'&&[9,13].includes(i)); | |||
| if(installation&&d.id.includes('-bolt-')){ | |||
| assert.equal(d.tray.items.find(item=>item.id===d.id).stored,false,'bolt leaves storage before tool use'); | |||
| assert.ok(Math.abs(d.mountingDistance-.008)<.00001,'bolt is staged at mounting hole before tool use'); | |||
| assert.equal(d.operation,j,'click placement never completes tightening');assert.ok(!d.complete); | |||
| assert.ok(d.frontAlignment>.95,'automatic camera faces mounting plane'); | |||
| checks.push({task:id,step:i+1,target:d.id,check:'bolt placed by click; tightening unconfirmed; front-facing camera',mountingDistance:d.mountingDistance}); | |||
| } | |||
| if(id==='89'&&[8,12].includes(i)&&d.id.includes('-plug-')){ | |||
| assert.equal(d.tool.trigger,'direct','plug removal must not require another plug'); | |||
| checks.push({task:id,step:i+1,target:d.id,check:'installed oil plug removed directly'}); | |||
| } | |||
| } | |||
| if(d.tool?.trigger==='tool-drop'){ | |||
| if(await page.locator('[data-toolbox-toggle]').getAttribute('aria-expanded')==='false')await page.locator('[data-toolbox-toggle]').click(); | |||
| if(process.env.KEEP_TEACHER==='1'){ | |||
| @@ -96,6 +136,7 @@ try{ | |||
| } | |||
| await page.locator('[data-role="part-label"]').click();await settle();d=await snap(); | |||
| assert.ok(d.points.length,'no visible pick point '+id+' step '+(i+1)+' '+d.id); | |||
| if(process.env.CHECK_INSTALLATION==='1'&&((id==='89'&&[9,13].includes(i))||(id==='88'&&i===7))&&d.id.includes('-bolt-'))await page.screenshot({path:dir+'/task-'+id+'-mount-step-'+(i+1)+'-bolt-'+j+'.png'}); | |||
| if(d.tool?.trigger==='tool-drop'&&!testedToolFailure){ | |||
| testedToolFailure=true; | |||
| const wrongId=(await page.locator('[data-bridge-tool]').evaluateAll(nodes=>nodes.map(n=>n.dataset.bridgeTool))).find(key=>key!==d.tool.toolId); | |||