diff --git a/reports/bridge-bolt-pick-20260925-007/result.json b/reports/bridge-bolt-pick-20260925-007/result.json
new file mode 100644
index 0000000..9ef26dc
--- /dev/null
+++ b/reports/bridge-bolt-pick-20260925-007/result.json
@@ -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": []
+}
\ No newline at end of file
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-1.png b/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-1.png
new file mode 100644
index 0000000..72094cb
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-1.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-2.png b/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-2.png
new file mode 100644
index 0000000..28e53f9
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-2.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-3.png b/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-3.png
new file mode 100644
index 0000000..474f87c
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-3.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-4.png b/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-4.png
new file mode 100644
index 0000000..44ad9cf
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-mount-step-8-bolt-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-overview.png b/reports/bridge-bolt-pick-20260925-007/task-88-overview.png
new file mode 100644
index 0000000..3b7a820
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-overview.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-1.png b/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-1.png
new file mode 100644
index 0000000..cf98b88
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-1.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-2.png b/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-2.png
new file mode 100644
index 0000000..b84cc7b
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-2.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-3.png b/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-3.png
new file mode 100644
index 0000000..0d96101
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-3.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-4.png b/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-4.png
new file mode 100644
index 0000000..181369c
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-pick-step-8-bolt-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-step-2.png b/reports/bridge-bolt-pick-20260925-007/task-88-step-2.png
new file mode 100644
index 0000000..d0b4b45
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-step-2.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-step-4.png b/reports/bridge-bolt-pick-20260925-007/task-88-step-4.png
new file mode 100644
index 0000000..840c7ca
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-step-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-step-8.png b/reports/bridge-bolt-pick-20260925-007/task-88-step-8.png
new file mode 100644
index 0000000..d6512c6
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-step-8.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-tool-step-4.png b/reports/bridge-bolt-pick-20260925-007/task-88-tool-step-4.png
new file mode 100644
index 0000000..2a9283a
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-tool-step-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-4.png b/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-4.png
new file mode 100644
index 0000000..840c7ca
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-7.png b/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-7.png
new file mode 100644
index 0000000..d74cf63
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-7.png differ
diff --git a/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-8.png b/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-8.png
new file mode 100644
index 0000000..d6512c6
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-007/task-88-tray-step-8.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/result.json b/reports/bridge-bolt-pick-20260925-008/result.json
new file mode 100644
index 0000000..41efcee
--- /dev/null
+++ b/reports/bridge-bolt-pick-20260925-008/result.json
@@ -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": []
+}
\ No newline at end of file
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-1.png b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-1.png
new file mode 100644
index 0000000..d8eb18e
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-1.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-2.png b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-2.png
new file mode 100644
index 0000000..924cb75
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-2.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-3.png b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-3.png
new file mode 100644
index 0000000..e6b6325
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-3.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-4.png b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-4.png
new file mode 100644
index 0000000..b288bf8
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-10-bolt-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-1.png b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-1.png
new file mode 100644
index 0000000..22a1932
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-1.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-2.png b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-2.png
new file mode 100644
index 0000000..993234d
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-2.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-3.png b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-3.png
new file mode 100644
index 0000000..dad0122
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-3.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-4.png b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-4.png
new file mode 100644
index 0000000..d7e4590
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-mount-step-14-bolt-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-overview.png b/reports/bridge-bolt-pick-20260925-008/task-89-overview.png
new file mode 100644
index 0000000..101473c
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-overview.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-1.png b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-1.png
new file mode 100644
index 0000000..63f7d2a
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-1.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-2.png b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-2.png
new file mode 100644
index 0000000..00f5b50
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-2.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-3.png b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-3.png
new file mode 100644
index 0000000..17d86e7
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-3.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-4.png b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-4.png
new file mode 100644
index 0000000..aac51a9
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-10-bolt-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-1.png b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-1.png
new file mode 100644
index 0000000..15601c1
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-1.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-2.png b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-2.png
new file mode 100644
index 0000000..8278d87
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-2.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-3.png b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-3.png
new file mode 100644
index 0000000..18548bd
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-3.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-4.png b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-4.png
new file mode 100644
index 0000000..0649857
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-pick-step-14-bolt-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-step-2.png b/reports/bridge-bolt-pick-20260925-008/task-89-step-2.png
new file mode 100644
index 0000000..297f68d
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-step-2.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-step-4.png b/reports/bridge-bolt-pick-20260925-008/task-89-step-4.png
new file mode 100644
index 0000000..374f31a
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-step-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-step-8.png b/reports/bridge-bolt-pick-20260925-008/task-89-step-8.png
new file mode 100644
index 0000000..464abf2
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-step-8.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-1.png b/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-1.png
new file mode 100644
index 0000000..0876302
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-1.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-4.png b/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-4.png
new file mode 100644
index 0000000..660d63d
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-8.png b/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-8.png
new file mode 100644
index 0000000..15fd264
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-tool-step-8.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-14.png b/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-14.png
new file mode 100644
index 0000000..36a226f
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-14.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-4.png b/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-4.png
new file mode 100644
index 0000000..374f31a
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-4.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-7.png b/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-7.png
new file mode 100644
index 0000000..0c0fa9c
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-7.png differ
diff --git a/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-8.png b/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-8.png
new file mode 100644
index 0000000..464abf2
Binary files /dev/null and b/reports/bridge-bolt-pick-20260925-008/task-89-tray-step-8.png differ
diff --git a/reports/bridge-bolt-pick-20260925/index.html b/reports/bridge-bolt-pick-20260925/index.html
new file mode 100644
index 0000000..042ed76
--- /dev/null
+++ b/reports/bridge-bolt-pick-20260925/index.html
@@ -0,0 +1,6 @@
+
螺栓:工作台取件 → 孔位就位 → 扳手紧固
+
+螺栓:工作台取件 → 孔位就位 → 扳手紧固
2026-09-25 · 本地 6180 / 6100 Gateway · 管理员教员预览 · 1440×900
+进入回装子操作时,螺栓留在工作台,视角聚焦待取件。点击原螺栓后播放就位动画,随后使用扳手完成紧固。查看标签只聚焦,不移动零件;就位不计为紧固完成。每颗螺栓分别执行这三个阶段。
保存准备记录、紧固提交失败时保留已就位的状态;允许再次拖入扳手重试。油堵直接拆卸和第 14 步安装面的正面视角继续保留。
+验证结果
007 从第 1 步走到第 8 步,008 从第 1 步走到第 14 步,覆盖全部 12 颗回装螺栓。使用真实模型点击、工具拖放及预览校验接口。检查取件前工具禁用、点击后仍未紧固、保存准备记录后位置保持、最后一颗螺栓提交失败后重试。相关 Node 测试及 pnpm run build 通过。没有创建学员成绩或测试任务。
+007 第 8 步 · 螺栓 1
点击前:工作台取件,工具暂不可用
点击后:安装孔位就位,等待扳手紧固008 第 10 步 · 螺栓 2
点击前:工作台取件,工具暂不可用
点击后:安装孔位就位,等待扳手紧固008 第 14 步 · 螺栓 3
点击前:工作台取件,工具暂不可用
点击后:安装孔位就位,等待扳手紧固
\ No newline at end of file
diff --git a/reports/bridge-installation-fixes-20260925-007/result.json b/reports/bridge-installation-fixes-20260925-007/result.json
new file mode 100644
index 0000000..220827d
--- /dev/null
+++ b/reports/bridge-installation-fixes-20260925-007/result.json
@@ -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": []
+}
\ No newline at end of file
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-1.png b/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-1.png
new file mode 100644
index 0000000..3aeba57
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-1.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-2.png b/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-2.png
new file mode 100644
index 0000000..a8454b2
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-2.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-3.png b/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-3.png
new file mode 100644
index 0000000..474f87c
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-3.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-4.png b/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-4.png
new file mode 100644
index 0000000..44ad9cf
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-mount-step-8-bolt-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-overview.png b/reports/bridge-installation-fixes-20260925-007/task-88-overview.png
new file mode 100644
index 0000000..3b7a820
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-overview.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-step-2.png b/reports/bridge-installation-fixes-20260925-007/task-88-step-2.png
new file mode 100644
index 0000000..a522afe
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-step-2.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-step-4.png b/reports/bridge-installation-fixes-20260925-007/task-88-step-4.png
new file mode 100644
index 0000000..840c7ca
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-step-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-step-8.png b/reports/bridge-installation-fixes-20260925-007/task-88-step-8.png
new file mode 100644
index 0000000..d6512c6
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-step-8.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-tool-step-4.png b/reports/bridge-installation-fixes-20260925-007/task-88-tool-step-4.png
new file mode 100644
index 0000000..5bb7612
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-tool-step-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-4.png b/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-4.png
new file mode 100644
index 0000000..840c7ca
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-7.png b/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-7.png
new file mode 100644
index 0000000..8537379
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-7.png differ
diff --git a/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-8.png b/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-8.png
new file mode 100644
index 0000000..d6512c6
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-007/task-88-tray-step-8.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/result.json b/reports/bridge-installation-fixes-20260925-008/result.json
new file mode 100644
index 0000000..d397fc0
--- /dev/null
+++ b/reports/bridge-installation-fixes-20260925-008/result.json
@@ -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": []
+}
\ No newline at end of file
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-1.png b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-1.png
new file mode 100644
index 0000000..d8eb18e
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-1.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-2.png b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-2.png
new file mode 100644
index 0000000..924cb75
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-2.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-3.png b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-3.png
new file mode 100644
index 0000000..e6b6325
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-3.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-4.png b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-4.png
new file mode 100644
index 0000000..b288bf8
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-10-bolt-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-1.png b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-1.png
new file mode 100644
index 0000000..fae77b8
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-1.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-2.png b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-2.png
new file mode 100644
index 0000000..21c3986
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-2.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-3.png b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-3.png
new file mode 100644
index 0000000..dad0122
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-3.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-4.png b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-4.png
new file mode 100644
index 0000000..2ddc21b
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-mount-step-14-bolt-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-overview.png b/reports/bridge-installation-fixes-20260925-008/task-89-overview.png
new file mode 100644
index 0000000..101473c
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-overview.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-step-2.png b/reports/bridge-installation-fixes-20260925-008/task-89-step-2.png
new file mode 100644
index 0000000..21c9768
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-step-2.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-step-4.png b/reports/bridge-installation-fixes-20260925-008/task-89-step-4.png
new file mode 100644
index 0000000..374f31a
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-step-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-step-8.png b/reports/bridge-installation-fixes-20260925-008/task-89-step-8.png
new file mode 100644
index 0000000..464abf2
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-step-8.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-1.png b/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-1.png
new file mode 100644
index 0000000..4178769
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-1.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-4.png b/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-4.png
new file mode 100644
index 0000000..5d7364f
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-8.png b/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-8.png
new file mode 100644
index 0000000..ec4f4f5
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-tool-step-8.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-14.png b/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-14.png
new file mode 100644
index 0000000..36a226f
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-14.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-4.png b/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-4.png
new file mode 100644
index 0000000..374f31a
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-4.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-7.png b/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-7.png
new file mode 100644
index 0000000..0c0fa9c
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-7.png differ
diff --git a/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-8.png b/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-8.png
new file mode 100644
index 0000000..464abf2
Binary files /dev/null and b/reports/bridge-installation-fixes-20260925-008/task-89-tray-step-8.png differ
diff --git a/reports/bridge-installation-fixes-20260925/index.html b/reports/bridge-installation-fixes-20260925/index.html
new file mode 100644
index 0000000..8e933b3
--- /dev/null
+++ b/reports/bridge-installation-fixes-20260925/index.html
@@ -0,0 +1,7 @@
+螺栓安装、油堵拆卸与平衡阀视角修正
+
+螺栓安装、油堵拆卸与平衡阀视角修正
2026-09-25 · 本地 6180 → 6100 Gateway · 维护账号教员预览 · 真实鼠标点击、工具拖放和服务端预览校验。
+完成内容
- 007、008 回装螺栓时,先把当前螺栓从暂存台送到安装孔,再等待学员用扳手紧固。搬运不完成子操作,不生成紧固证据。
- 008 第 9、13 步的油堵直接点击或拖动取下;第 4、8 步封堵仍使用工具箱油堵。
- 008 两侧螺栓按真实安装面法线设置视角,互换后的阀体跟随目的安装面。被交换阀体遮住的螺栓仍可见、可拾取。
- 保存失败恢复到待紧固位置,允许再次使用工具;不改写已发布任务、步骤数量或评分规则。
+验证
相关 Node 自动测试、正式路由契约和前端生产构建通过。007、008 全流程使用正式页面与预览接口;模拟最后一颗安装螺栓保存失败并重试。未创建学员成绩或测试教学任务。
+
007:新泵安装后的第一颗螺栓,已到孔位,等待拖入扳手。
008 第 10 步:大腔螺栓在安装位置等待工具,暂存台上的其余零件保持原位。
008 第 14 步:第 3 颗小腔螺栓,从安装面正面观察。
+
\ No newline at end of file
diff --git a/tools/bridge-bolt-pick-report.mjs b/tools/bridge-bolt-pick-report.mjs
new file mode 100644
index 0000000..6849803
--- /dev/null
+++ b/tools/bridge-bolt-pick-report.mjs
@@ -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`,`螺栓:工作台取件 → 孔位就位 → 扳手紧固
+
+螺栓:工作台取件 → 孔位就位 → 扳手紧固
2026-09-25 · 本地 6180 / 6100 Gateway · 管理员教员预览 · 1440×900
+进入回装子操作时,螺栓留在工作台,视角聚焦待取件。点击原螺栓后播放就位动画,随后使用扳手完成紧固。查看标签只聚焦,不移动零件;就位不计为紧固完成。每颗螺栓分别执行这三个阶段。
保存准备记录、紧固提交失败时保留已就位的状态;允许再次拖入扳手重试。油堵直接拆卸和第 14 步安装面的正面视角继续保留。
+验证结果
007 从第 1 步走到第 8 步,008 从第 1 步走到第 14 步,覆盖全部 12 颗回装螺栓。使用真实模型点击、工具拖放及预览校验接口。检查取件前工具禁用、点击后仍未紧固、保存准备记录后位置保持、最后一颗螺栓提交失败后重试。相关 Node 测试及 pnpm run build 通过。没有创建学员成绩或测试任务。
${results.map(r=>`- ${r.script}:${r.checks.length} 条检查通过,${r.errors.length} 个页面脚本错误。JSON 记录
`).join('')}
+${figures.map(([script,id,step,bolt])=>`${script} 第 ${step} 步 · 螺栓 ${bolt}
${[['pick','点击前:工作台取件,工具暂不可用'],['mount','点击后:安装孔位就位,等待扳手紧固']].map(([phase,title])=>`
${title}`).join('')}
`).join('')}`);
+console.log(`${dir}/index.html`);
diff --git a/tools/bridge-installation-report.mjs b/tools/bridge-installation-report.mjs
new file mode 100644
index 0000000..3273523
--- /dev/null
+++ b/tools/bridge-installation-report.mjs
@@ -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`,`螺栓安装、油堵拆卸与平衡阀视角修正
+
+螺栓安装、油堵拆卸与平衡阀视角修正
2026-09-25 · 本地 6180 → 6100 Gateway · 维护账号教员预览 · 真实鼠标点击、工具拖放和服务端预览校验。
+完成内容
- 007、008 回装螺栓时,先把当前螺栓从暂存台送到安装孔,再等待学员用扳手紧固。搬运不完成子操作,不生成紧固证据。
- 008 第 9、13 步的油堵直接点击或拖动取下;第 4、8 步封堵仍使用工具箱油堵。
- 008 两侧螺栓按真实安装面法线设置视角,互换后的阀体跟随目的安装面。被交换阀体遮住的螺栓仍可见、可拾取。
- 保存失败恢复到待紧固位置,允许再次使用工具;不改写已发布任务、步骤数量或评分规则。
+验证
相关 Node 自动测试、正式路由契约和前端生产构建通过。007、008 全流程使用正式页面与预览接口;模拟最后一颗安装螺栓保存失败并重试。未创建学员成绩或测试教学任务。
${results.map(({name,result})=>`- ${name}:通过,${result.checks.length} 条检查,${result.errors.length} 个页面脚本错误。
`).join('')}
+${figures.map(([suffix,id,step,bolt,caption])=>`
${caption}`).join('')}
+`);
+console.log(`${dir}/index.html`);
diff --git a/tools/bridge-training-safety-live.mjs b/tools/bridge-training-safety-live.mjs
index 13c7b2f..1035e61 100644
--- a/tools/bridge-training-safety-live.mjs
+++ b/tools/bridge-training-safety-live.mjs
@@ -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;jitem.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);