devagent-ignition 0.1.6__tar.gz → 0.1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/PKG-INFO +1 -1
  2. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/SHA256SUMS.txt +4 -3
  3. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/three_scene.js +36 -10
  4. devagent_ignition-0.1.8/devagent_spatial/__init__.py +1 -0
  5. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/model.py +30 -3
  6. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/pyproject.toml +1 -1
  7. devagent_ignition-0.1.6/devagent_spatial/__init__.py +0 -1
  8. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/.gitignore +0 -0
  9. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/README.md +0 -0
  10. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/RELEASE_MANIFEST.json +0 -0
  11. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/SOURCE_PROVENANCE.json +0 -0
  12. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/agent.js +0 -0
  13. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/creator.css +0 -0
  14. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/creator_2d.mjs +0 -0
  15. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/creator_original_r9.mjs +0 -0
  16. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/creator_original_v8.mjs +0 -0
  17. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/creator_r9_diagnostics.mjs +0 -0
  18. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/creator_scene.mjs +0 -0
  19. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/creator_ui.mjs +0 -0
  20. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/customer_documents.js +0 -0
  21. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/equipment_controls.mjs +0 -0
  22. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/facility2d.css +0 -0
  23. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/facility2d_app.mjs +0 -0
  24. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/facility2d_core.mjs +0 -0
  25. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/facility2d_simulation.mjs +0 -0
  26. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/facility2d_viewer.html +0 -0
  27. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/fallback_scene.js +0 -0
  28. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/flow_geometry.mjs +0 -0
  29. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/harness.js +0 -0
  30. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/live_design_review.js +0 -0
  31. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/operations_ui.js +0 -0
  32. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/operator_viewer.html +0 -0
  33. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/project_package.js +0 -0
  34. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/r9_transport.mjs +0 -0
  35. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/runtime_feed.js +0 -0
  36. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/studio.html +0 -0
  37. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/style.css +0 -0
  38. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/test_workspace.html +0 -0
  39. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/unified_engineer.js +0 -0
  40. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/v076_fat_ui.js +0 -0
  41. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/v078_command_ui.js +0 -0
  42. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/viewer.html +0 -0
  43. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/assets/viewer.js +0 -0
  44. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/design-system.json +0 -0
  45. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_hmi.py +0 -0
  46. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/agent_harness.py +0 -0
  47. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/agent_runtime.py +0 -0
  48. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/contract_opc_fat.py +0 -0
  49. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/contract_opc_source.py +0 -0
  50. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/control_intents.py +0 -0
  51. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/customer_intake.py +0 -0
  52. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/engineering_expertise.py +0 -0
  53. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/generator.py +0 -0
  54. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/ignition_native.py +0 -0
  55. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/ignition_project.py +0 -0
  56. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/industrial_templates.py +0 -0
  57. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/live_lab_binding.py +0 -0
  58. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/native_reference.py +0 -0
  59. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/opc_snapshot.py +0 -0
  60. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/operations.py +0 -0
  61. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/operations_capture.py +0 -0
  62. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/operations_lab.py +0 -0
  63. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/original_r9.py +0 -0
  64. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/original_v8.py +0 -0
  65. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/preflight.py +0 -0
  66. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/preview_simulation.py +0 -0
  67. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/project_package.py +0 -0
  68. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/qualification.py +0 -0
  69. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/strict_json.py +0 -0
  70. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/studio.py +0 -0
  71. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/studio_workflow.py +0 -0
  72. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/test_reporting.py +0 -0
  73. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/v076_opc_fat.py +0 -0
  74. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/v078_commands.py +0 -0
  75. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/v078_native_commands.py +0 -0
  76. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/v07_fat.py +0 -0
  77. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/v07_native.py +0 -0
  78. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/devagent_spatial/v083_native.py +0 -0
  79. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/CV101-command-contract-PENDING.json +0 -0
  80. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/cv101_guided.json +0 -0
  81. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/make_examples.py +0 -0
  82. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/single_floor.json +0 -0
  83. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/v0771_training_wizard.json +0 -0
  84. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/warehouse-3floor-standard-2d.json +0 -0
  85. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/warehouse-operations-synthetic.json +0 -0
  86. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/warehouse-v07-lab-bindings-PENDING.json +0 -0
  87. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/warehouse.json +0 -0
  88. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/examples/water.json +0 -0
  89. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-golden/REFERENCE_SHA256.json +0 -0
  90. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-golden/web/app.mjs +0 -0
  91. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-golden/web/index.html +0 -0
  92. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-golden/web/lab_panel.mjs +0 -0
  93. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-golden/web/model.mjs +0 -0
  94. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-golden/web/state_adapter.mjs +0 -0
  95. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-golden/web/styles.css +0 -0
  96. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/README_R9.md +0 -0
  97. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/SHA256SUMS.txt +0 -0
  98. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/SNAPSHOT_SHA256SUMS.txt +0 -0
  99. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/flow_routes.json +0 -0
  100. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/flow_sim.py +0 -0
  101. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/lab_control.py +0 -0
  102. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/app.mjs +0 -0
  103. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/index.html +0 -0
  104. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/lab_panel.mjs +0 -0
  105. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/model.mjs +0 -0
  106. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/state_adapter.mjs +0 -0
  107. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/styles.css +0 -0
  108. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/vendor/LICENSE-three.txt +0 -0
  109. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/vendor/SHA256SUMS.txt +0 -0
  110. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/vendor/addons/controls/OrbitControls.js +0 -0
  111. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/vendor/three.core.js +0 -0
  112. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/r9-original/web/vendor/three.module.js +0 -0
  113. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/README.md +0 -0
  114. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/SHA256SUMS.txt +0 -0
  115. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/model.py +0 -0
  116. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/run_demo.sh +0 -0
  117. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/server.py +0 -0
  118. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/tests/browser_smoke.py +0 -0
  119. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/tests/test_v8.py +0 -0
  120. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/topology.json +0 -0
  121. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/web/app.js +0 -0
  122. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/web/index.html +0 -0
  123. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/web/simulator.html +0 -0
  124. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/web/simulator.js +0 -0
  125. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/reference/v8-original/web/style.css +0 -0
  126. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/sample_customer_inputs/Plant_Equipment_Register.csv +0 -0
  127. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/sample_customer_inputs/Plant_Flow_Requirements.txt +0 -0
  128. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/sample_customer_inputs/Raw_PLC_Tag_Export.csv +0 -0
  129. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/templates/warehouse_connections.csv +0 -0
  130. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/templates/warehouse_equipment.csv +0 -0
  131. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/templates/warehouse_signals.csv +0 -0
  132. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/templates/water_connections.csv +0 -0
  133. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/templates/water_equipment.csv +0 -0
  134. {devagent_ignition-0.1.6 → devagent_ignition-0.1.8}/templates/water_signals.csv +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: devagent-ignition
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Offline industrial HMI engineering and Ignition Perspective candidate tools (production deployment not qualified)
5
5
  Project-URL: Repository, https://github.com/tomha85/devagent-ignition
6
6
  Project-URL: Documentation, https://github.com/tomha85/devagent-ignition#readme
@@ -28,7 +28,7 @@ c6b47941a2ffe72d297d329899b252f898904a0f37c1592689eeb81e0815147c assets/runtime
28
28
  6f0dcc9f218455b708552daa0536b2afb2d68b4095a1a6956f2147c329a6ff2f assets/studio.html
29
29
  c9f87624386bbe84ab7d71f93708f00f91a69e0d9693738cfee51913e5831fdf assets/style.css
30
30
  fd0d07ddec872de25c4e485573d5aa5b0c7a2c3137a93e65c6406b637fad7ad7 assets/test_workspace.html
31
- 17c987f61024400d756335e69579a0156bb097a237df64dd965165235d0eca1a assets/three_scene.js
31
+ 1463a628e50ba2f355e621372386777cd5d03c0c07aaec351e468c68ae9fc1dc assets/three_scene.js
32
32
  af23f86ef51e18dfc94355e77fe9fb52570db14466d05d6dadededf17458fe25 assets/unified_engineer.js
33
33
  531c378fe3aae0c1d0686da48d7a4eba371ca7641b343b952dc8448f1cf65dc1 assets/v076_fat_ui.js
34
34
  d009f79a79ed1278911c81818b97a7dbce72464b599bb00f6116b81e1b1f9b5c assets/v078_command_ui.js
@@ -39,7 +39,7 @@ d009f79a79ed1278911c81818b97a7dbce72464b599bb00f6116b81e1b1f9b5c assets/v078_co
39
39
  7ca0cdaea16239fc543fa63a5079fe40e4192c5281dc88085c5959ea5f350359 DESIGN_STANDARD_V1.md
40
40
  54ee77ca35589b06bd093204c9e5b28eabb69a8b2158ef1be5897386d3676c3f design-system.json
41
41
  287744606d4ec09533bb0af2ab6c1e059e614a7d87bc8c365d0f1e16c646bff8 devagent_hmi.py
42
- 816e4d531c0674fb224239f470ebae413d75a5fb610722390c84c383f1cc84b4 devagent_spatial/__init__.py
42
+ aeae4e316fa4871428ff9140bd2acf6804b59517c6f5a1b6852ba8f8a2b661f9 devagent_spatial/__init__.py
43
43
  a6b1a2a97e2ec31e2de7f4c576b9482f66d3aa7fb356b06f0475bcd221dd8116 devagent_spatial/agent_harness.py
44
44
  a54c22bb64e5ff6b8d720bc44a73d851388f3f55adcba0f5f17098349895f2a4 devagent_spatial/agent_runtime.py
45
45
  f57e58f596ab5395b5a9692158cca43866de32ec9f8d07bdec363a36610e3d2b devagent_spatial/contract_opc_fat.py
@@ -52,7 +52,7 @@ aaf9f671ccc950c5fdca0c99380a7a6191b0f9b31b31c7a48b3bc6826847808c devagent_spati
52
52
  9d40bfef7028aee2beae02420d36ae288b38380caf0d761b990c67d1e4c37683 devagent_spatial/ignition_project.py
53
53
  a6bf1fc83cdbd9a72ae5e9a10ae720682ae3e1b34b00a5a8f9148396a5e1b560 devagent_spatial/industrial_templates.py
54
54
  ad94f2d37437ffc9423b78faa99d418bc2696a2804351adc848e0eacaa3fc1c3 devagent_spatial/live_lab_binding.py
55
- 7b0ee190fee41846123400b588ca9886a9e2ac2a62760b669c33454cb11f9456 devagent_spatial/model.py
55
+ 5bab2411fe0fc10d3749cdd11ccdd9724018398a6f71dd220ba46c36367e93c0 devagent_spatial/model.py
56
56
  08f25a636ac26e5101ac1a6fbd52d8d4ac20be39d4ec75758b24fe3a070bc51f devagent_spatial/native_reference.py
57
57
  8ea7291ca8642d3e533f54b53fc95a93625c69aa8473c54a9bd0040b1bd50132 devagent_spatial/opc_snapshot.py
58
58
  cae72ca33644c7715faf49da021b221ff0a9c494803ba2893cc0fb66a6c19462 devagent_spatial/operations_capture.py
@@ -161,6 +161,7 @@ b009ba2cb868ea4095db7b3e9167976bda36db9838989a62e678d1aad72ee9f8 tests/test_age
161
161
  2e1ba68e65997568f3a46392cb196c5a1817475c226c10d00b6f8670b27c6098 tests/test_creator_codex_v081_stage1.py
162
162
  2fc73d9b284da9e8d262c63d50cf0410fe0dfc7a164e9945cf64ea42c4b7f29c tests/test_creator_v082_original_r9.py
163
163
  9a2cb6cd2bc20e0e4951f8a653da557da4ed83b22daf55a8a62a16f8306b6521 tests/test_design_lock_v043.py
164
+ 1afbb48ef333484714f360c7a73124f55eb8eba2ccbd53170fa6baf632391b11 tests/test_docks_drive_relation_contract.py
164
165
  d2720d9fa7a7e6e4d94bed62df6e9fb820edb5742d290d5b6484589dd902f244 tests/test_engine.py
165
166
  efd6b4d33d4af91f8a7e0f87198c5b1da3ca0abe69d517e774493b5c93a0396e tests/test_flexible_inputs_v021.py
166
167
  1ae0456b27443d3a6fab106fd365d0b9019f726a11c137f3ebb7f51381dfcb34 tests/test_flow_module_http_v052r1.py
@@ -35,7 +35,7 @@ export async function startThree(model,host,onSelect){
35
35
  const rim=new T.DirectionalLight(0x3cc0c0,1.05);rim.position.set(-10,10,-22);scene.add(rim);
36
36
  const warm=new T.PointLight(0xf1d294,28,65);warm.position.set(7,18,-7);scene.add(warm); // R9 key light; decorative only
37
37
  // Conceptual industrial materials, not operating-status colors.
38
- const col={conveyor:0x467e94,spiral:0x4c92a5,sorter:0x4a91a3,motor:0x6a879d,vfd:0x53748e,photoeye:0x43b7ad,scanner:0xbdaa6f,tank:0x668c9e,pump:0x6e91ab,valve:0xcaa86a,robot:0x82acb7,junction:0x467e94,room:0x365e78,other:0x628ca0};
38
+ const col={conveyor:0x467e94,spiral:0x4c92a5,sorter:0x4a91a3,motor:0x6a879d,vfd:0x53748e,photoeye:0x43b7ad,scanner:0xbdaa6f,tank:0x668c9e,pump:0x6e91ab,valve:0xcaa86a,robot:0x82acb7,junction:0x467e94,room:0x365e78,dock_door:0x688fa0,dock_leveler:0x7e95a2,other:0x628ca0};
39
39
  const mats={
40
40
  frame:new T.MeshStandardMaterial({color:0x627e8d,metalness:.63,roughness:.41}),
41
41
  trim:new T.MeshStandardMaterial({color:0xa5c1ca,metalness:.68,roughness:.32}),
@@ -47,12 +47,12 @@ export async function startThree(model,host,onSelect){
47
47
  highlight:new T.MeshStandardMaterial({color:0xd6b66e,metalness:.54,roughness:.42}),
48
48
  };
49
49
  const mat=(c,metal=.48,rough=.48,opacity=1)=>new T.MeshStandardMaterial({color:c,metalness:metal,roughness:rough,transparent:opacity<1,opacity,side:T.DoubleSide});
50
- const assets=new Map(),pickables=[],floors=new Map(),sensorLamps=new Map();
50
+ const assets=new Map(),pickables=[],floors=new Map(),sensorLamps=new Map(),assetLabels=new Map();
51
51
  const boxGeometry=new T.BoxGeometry(1,1,1);
52
52
  function box(g,x,y,z,dx,dy,dz,m){const o=new T.Mesh(boxGeometry,m);o.position.set(x,y,z);o.scale.set(Math.max(.03,dx),Math.max(.03,dy),Math.max(.03,dz));o.castShadow=true;o.receiveShadow=true;g.add(o);return o;}
53
53
  function cylinder(g,x,y,z,rad,height,m,segments=20){const o=new T.Mesh(new T.CylinderGeometry(rad,rad,height,segments),m);o.position.set(x,y,z);o.castShadow=true;o.receiveShadow=true;g.add(o);return o;}
54
54
  function rail(g,sx,y,z){box(g,0,y,z,sx,.12,.10,mats.trim);box(g,0,y+.12,z,sx,.065,.08,mats.frame);}
55
- function label(text){const cv=document.createElement('canvas');cv.width=384;cv.height=90;const ctx=cv.getContext('2d');ctx.fillStyle='rgba(7,24,37,.94)';ctx.fillRect(2,4,380,82);ctx.strokeStyle='#7494a4';ctx.lineWidth=2;ctx.strokeRect(2,4,380,82);ctx.fillStyle='#e1f7ff';ctx.font='bold 37px system-ui';ctx.textAlign='center';ctx.textBaseline='middle';ctx.fillText(text.slice(0,20),192,46);const tex=new T.CanvasTexture(cv);tex.colorSpace=T.SRGBColorSpace;const sprite=new T.Sprite(new T.SpriteMaterial({map:tex,transparent:true,depthWrite:false}));sprite.scale.set(3.0,.72,1);return sprite;}
55
+ function label(text){const cv=document.createElement('canvas');cv.width=384;cv.height=90;const ctx=cv.getContext('2d');ctx.fillStyle='rgba(3,17,29,.99)';ctx.fillRect(2,4,380,82);ctx.strokeStyle='#b2d9ee';ctx.lineWidth=2;ctx.strokeRect(2,4,380,82);ctx.fillStyle='#ffffff';ctx.font='800 44px system-ui';ctx.textAlign='center';ctx.textBaseline='middle';ctx.fillText(text.slice(0,20),192,46);const tex=new T.CanvasTexture(cv);tex.colorSpace=T.SRGBColorSpace;const sprite=new T.Sprite(new T.SpriteMaterial({map:tex,transparent:true,depthWrite:false}));sprite.scale.set(3.45,.78,1);return sprite;}
56
56
  function line(a,b,color=palette.edge){const geom=new T.BufferGeometry().setFromPoints([a,b]);const obj=new T.Line(geom,new T.LineDashedMaterial({color,dashSize:.26,gapSize:.16,opacity:.74,transparent:true}));obj.computeLineDistances();return obj;}
57
57
  const floorNs=[...new Set(model.equipment.map(e=>e.floor))].sort((a,b)=>a-b);
58
58
  const facility=commonFacilityBounds(model);
@@ -178,6 +178,18 @@ export async function startThree(model,host,onSelect){
178
178
  box(g,0,1.62,0,.16,.18,1.63,mats.trim);
179
179
  box(g,0,1.62,0,.42,.23,.49,mat(base));
180
180
  box(g,0,1.48,.13,.22,.06,.27,mats.dark);
181
+ } else if(kind==='dock_door'){
182
+ // Distinct receiving/shipping dock opening; architectural concept only.
183
+ box(g,0,2.3,0,3.15,4.5,.20,mats.frame);
184
+ box(g,0,2.2,.15,2.75,3.9,.09,mats.dark);
185
+ for(let y=.55;y<3.95;y+=.64)box(g,0,y,.24,2.60,.055,.06,mats.trim);
186
+ box(g,-1.5,2.25,.20,.15,4.4,.20,mats.highlight);
187
+ box(g,1.5,2.25,.20,.15,4.4,.20,mats.highlight);
188
+ } else if(kind==='dock_leveler'){
189
+ // Loading ramp is a separate model, not a material handling connection.
190
+ box(g,0,.16,0,2.7,.18,2.35,mats.frame);
191
+ const ramp=box(g,.08,.28,.35,2.30,.075,1.8,mats.highlight);
192
+ ramp.rotation.x=-.08;
181
193
  } else if(kind==='vfd'||kind==='motor'){
182
194
  box(g,0,Math.max(.4,sy*.5),0,sx,Math.max(.7,sy),sz,mat(base,.55,.52));
183
195
  box(g,0,sy*.61,sz*.53,sx*.77,sy*.44,.075,mats.dark);
@@ -197,7 +209,7 @@ export async function startThree(model,host,onSelect){
197
209
  box(g,0,Math.max(.25,sy*.5),0,sx,sy,sz,mat(base));
198
210
  box(g,0,Math.max(.4,sy),0,sx*.86,.085,sz*.82,mats.trim);
199
211
  }
200
- const name=label(e.id);name.position.set(0,Math.max(.8,sy)+.95,0);g.add(name);
212
+ const name=label(e.id);name.position.set(0,Math.max(.8,sy)+.95,0);name.userData.isEquipmentLabel=true;g.add(name);assetLabels.set(e.id,name);
201
213
  // Accessible click targets: industrial belts are too thin for reliable picking.
202
214
  // Invisible proxy is local to the asset group, never rendered, never collidable.
203
215
  const isTransport=['conveyor','sorter','junction'].includes(kind);
@@ -379,7 +391,21 @@ export async function startThree(model,host,onSelect){
379
391
  }
380
392
  }
381
393
  const ray=new T.Raycaster();const cursor=new T.Vector2();let selectedId=null;
382
- function selected(id){selectedId=id;const g=assets.get(id);selectRing.visible=!!g;if(g){const e=model.equipment.find(x=>x.id===id);selectRing.position.set(g.position.x,e.position.y-.42,g.position.z);selectRing.scale.setScalar(Math.max(1,Math.min(2.5,e.dimensions.x*.48)));}}
394
+ // Progressive label disclosure keeps large R9-style warehouse overviews legible.
395
+ // No inferred equipment relationships or operational status.
396
+ function refreshLabels(){
397
+ const candidates=model.equipment.filter(e=>visibleFloor==='all'||String(e.floor)===visibleFloor);
398
+ const near=dist<33,mid=dist<95;
399
+ const stride=near?1:Math.max(1,Math.ceil(candidates.length/(mid?32:18)));
400
+ let i=0;
401
+ for(const e of model.equipment){
402
+ const sprite=assetLabels.get(e.id);if(!sprite)continue;
403
+ const inFloor=visibleFloor==='all'||String(e.floor)===visibleFloor;
404
+ sprite.visible=inFloor&&(e.id===selectedId||near||(i++%stride===0));
405
+ }
406
+ }
407
+
408
+ function selected(id){selectedId=id;const g=assets.get(id);selectRing.visible=!!g;refreshLabels();if(g){const e=model.equipment.find(x=>x.id===id);selectRing.position.set(g.position.x,e.position.y-.42,g.position.z);selectRing.scale.setScalar(Math.max(1,Math.min(2.5,e.dimensions.x*.48)));}}
383
409
  // Frame each customer facility, independent of floor count or asset quantity.
384
410
  const bb=new T.Box3();
385
411
  for(const e of model.equipment){
@@ -396,7 +422,7 @@ export async function startThree(model,host,onSelect){
396
422
  function fitCamera(){
397
423
  if(activeBox.isEmpty())return;
398
424
  const w=Math.max(320,host.clientWidth||1100),h=Math.max(280,host.clientHeight||640);
399
- const aspect=w/h,halfAngle=T.MathUtils.degToRad(camera.fov*.5),m=.85;
425
+ const aspect=w/h,halfAngle=T.MathUtils.degToRad(camera.fov*.5),m=.93;
400
426
  const n=new T.Vector3(Math.cos(el)*Math.sin(az),Math.sin(el),Math.cos(el)*Math.cos(az));
401
427
  const right=new T.Vector3(Math.cos(az),0,-Math.sin(az));
402
428
  const up=new T.Vector3().crossVectors(n,right).normalize();
@@ -428,20 +454,20 @@ export async function startThree(model,host,onSelect){
428
454
  activeBox.expandByPoint(p.clone().sub(h));activeBox.expandByPoint(p.clone().add(h));
429
455
  }
430
456
  if(!activeBox.isEmpty())target.copy(activeBox.getCenter(new T.Vector3()));
431
- fitCamera();updateCamera();
457
+ fitCamera();updateCamera();refreshLabels();
432
458
  }
433
459
  let dragging=false,moved=false,px=0,py=0,startX=0,startY=0;
434
460
  renderer.domElement.style.touchAction='none';
435
461
  renderer.domElement.addEventListener('pointerdown',ev=>{if(ev.button!==0)return;dragging=true;moved=false;startX=px=ev.clientX;startY=py=ev.clientY;renderer.domElement.setPointerCapture(ev.pointerId);});
436
- renderer.domElement.addEventListener('pointermove',ev=>{if(!dragging)return;const dx=ev.clientX-px,dy=ev.clientY-py;px=ev.clientX;py=ev.clientY;if(Math.hypot(ev.clientX-startX,ev.clientY-startY)>6)moved=true;if(!moved)return;az-=dx*.006;el=Math.max(.08,Math.min(1.5,el+dy*.006));updateCamera();});
462
+ renderer.domElement.addEventListener('pointermove',ev=>{if(!dragging)return;const dx=ev.clientX-px,dy=ev.clientY-py;px=ev.clientX;py=ev.clientY;if(Math.hypot(ev.clientX-startX,ev.clientY-startY)>6)moved=true;if(!moved)return;az-=dx*.006;el=Math.max(.08,Math.min(1.5,el+dy*.006));updateCamera();refreshLabels();});
437
463
  renderer.domElement.addEventListener('pointercancel',()=>{dragging=false;});
438
464
  renderer.domElement.addEventListener('pointerup',ev=>{if(!dragging)return;dragging=false;if(moved)return;
439
465
  const box=renderer.domElement.getBoundingClientRect();cursor.x=((ev.clientX-box.left)/box.width)*2-1;cursor.y=-((ev.clientY-box.top)/box.height)*2+1;ray.setFromCamera(cursor,camera);
440
466
  const isVisible=o=>{while(o&&o!==scene){if(!o.visible)return false;o=o.parent;}return true;};
441
467
  const chosen=ray.intersectObjects(pickables,false).find(h=>isVisible(h.object)&&h.object.userData.asset);
442
468
  if(chosen)onSelect(chosen.object.userData.asset);
443
- });renderer.domElement.addEventListener('wheel',ev=>{ev.preventDefault();dist=Math.min(260,Math.max(6,dist*(ev.deltaY>0?1.11:.90)));updateCamera();},{passive:false});
444
- function resize(){const r=host.getBoundingClientRect();renderer.setSize(Math.max(320,r.width),Math.max(280,r.height),false);camera.aspect=Math.max(320,r.width)/Math.max(280,r.height);camera.updateProjectionMatrix();fitCamera();updateCamera();}const obs=new ResizeObserver(resize);obs.observe(host);resize();let active=true;
469
+ });renderer.domElement.addEventListener('wheel',ev=>{ev.preventDefault();dist=Math.min(260,Math.max(6,dist*(ev.deltaY>0?1.11:.90)));updateCamera();refreshLabels();},{passive:false});
470
+ function resize(){const r=host.getBoundingClientRect();renderer.setSize(Math.max(320,r.width),Math.max(280,r.height),false);camera.aspect=Math.max(320,r.width)/Math.max(280,r.height);camera.updateProjectionMatrix();fitCamera();updateCamera();}const obs=new ResizeObserver(resize);obs.observe(host);resize();refreshLabels();let active=true;
445
471
  function frame(){if(!active)return;
446
472
  const now=performance.now();
447
473
  for(const obj of simulatedParcels.values()){
@@ -0,0 +1 @@
1
+ __version__ = '0.1.8'
@@ -8,7 +8,7 @@ from dataclasses import dataclass, asdict
8
8
  from typing import Any
9
9
 
10
10
  ID = re.compile(r'^[A-Z][A-Z0-9_]{1,31}$')
11
- KINDS = frozenset('conveyor spiral sorter motor vfd photoeye scanner tank pump valve robot junction room other'.split())
11
+ KINDS = frozenset('conveyor spiral sorter motor vfd photoeye scanner tank pump valve robot junction room dock_door dock_leveler other'.split())
12
12
  LAYOUTS = frozenset(('spatial_overview', 'process_flow', 'standard_2d_flow', 'machine_detail', 'multi_zone'))
13
13
  ROLES = {
14
14
  'run_feedback': ('Boolean', None),
@@ -35,7 +35,8 @@ ROLES = {
35
35
  NUMERIC = {'Int32', 'Double'}
36
36
  MAX_EQUIPMENT, MAX_SIGNALS, MAX_CONNECTIONS, MAX_REQUIREMENTS = 150, 1200, 400, 200
37
37
  PALETTES = frozenset({'r9_cyan', 'steel_blue', 'teal', 'warm_amber'})
38
- ALLOWED_ROOT = {'schema_version','name','industry','description','layout','theme','palette','equipment','connections','signals','requirements'}
38
+ ALLOWED_ROOT = {'schema_version','name','industry','description','layout','theme','palette','equipment','connections','signals','requirements','drive_relations'}
39
+ ALLOWED_DRIVE_RELATION = {'vfd_id','motor_ids','equipment_id','source_document'}
39
40
  ALLOWED_EQUIPMENT = {'id','name','kind','floor','zone','position','dimensions'}
40
41
  ALLOWED_SIGNAL = {'id','asset_id','role','datatype','unit','polarity','source','write_authorized'}
41
42
  ALLOWED_SOURCE = {'namespace_uri','node_id'}
@@ -55,7 +56,7 @@ DEFAULT_SIZES = {
55
56
  'motor': (.8, .7, .9), 'vfd': (.8, 1.8, .5), 'photoeye': (.3, 1.1, .3),
56
57
  'scanner': (.7, 1.4, .6), 'tank': (3, 5, 3), 'pump': (1.6, 1, 1.3),
57
58
  'valve': (.6, .7, .6), 'robot': (2, 2.8, 2), 'junction': (1.8, .4, 1.8),
58
- 'room': (4, 3, 4), 'other': (2, 1, 2),
59
+ 'room': (4, 3, 4), 'dock_door': (3, 4, .4), 'dock_leveler': (2.5, .25, 2), 'other': (2, 1, 2),
59
60
  }
60
61
 
61
62
 
@@ -159,6 +160,32 @@ def clean_project(data: Any) -> tuple[dict, list[Issue]]:
159
160
  dims = e.get('dimensions')
160
161
  if dims is not None and (not isinstance(dims, dict) or set(dims) != {'x','y','z'} or not all(k in dims and type(dims[k]) in (int, float) and math.isfinite(dims[k]) and .15 <= dims[k] <= 50 for k in ('x', 'y', 'z'))):
161
162
  issue(problems, 'HOLD', 'INVALID_DIMENSIONS', path+'.dimensions', 'Use finite positive x,y,z (0.15–50)')
163
+ # An explicit engineering declaration is required for every drive-to-motor
164
+ # relation. Never auto-associate from asset ID, proximity, or flow edges.
165
+ drive_relations = data.get('drive_relations', [])
166
+ if not isinstance(drive_relations,list) or len(drive_relations)>MAX_EQUIPMENT:
167
+ issue(problems,'HOLD','DRIVE_RELATIONS_COUNT','drive_relations','Expected bounded relation list')
168
+ drive_relations=[]
169
+ kinds_by_id = {e.get('id'):e.get('kind') for e in eq if isinstance(e,dict) and isinstance(e.get('id'),str)}
170
+ claimed_motors=set()
171
+ for i, rel in enumerate(drive_relations):
172
+ path=f'drive_relations[{i}]'
173
+ if not isinstance(rel,dict):
174
+ issue(problems,'HOLD','INVALID_DRIVE_RELATION',path,'Expected object')
175
+ continue
176
+ check_fields(rel,ALLOWED_DRIVE_RELATION,problems,path)
177
+ vfd,motors,asset,source=(rel.get(k) for k in ('vfd_id','motor_ids','equipment_id','source_document'))
178
+ if (not isinstance(vfd,str) or not isinstance(asset,str) or
179
+ kinds_by_id.get(vfd)!='vfd' or kinds_by_id.get(asset) not in ('conveyor','sorter','spiral')):
180
+ issue(problems,'HOLD','DRIVE_ASSET_KIND',path,'Declared drive and driven equipment must exist with matching kinds')
181
+ if not isinstance(motors,list) or not motors or len(motors)>16 or len(set(map(str,motors)))!=len(motors) or any(kinds_by_id.get(x)!='motor' for x in motors if isinstance(x,str)) or any(not isinstance(x,str) for x in motors):
182
+ issue(problems,'HOLD','DRIVE_MOTOR_IDS',path,'Require 1-16 unique declared motor IDs')
183
+ continue
184
+ if not isinstance(source,str) or not 1<=len(source.strip())<=240:
185
+ issue(problems,'HOLD','DRIVE_SOURCE_MISSING',path,'Customer engineering source reference required')
186
+ if any(m in claimed_motors for m in motors):
187
+ issue(problems,'HOLD','MULTIPLE_VFD_OWNERS',path,'Motor ownership ambiguous across drive declarations')
188
+ claimed_motors.update(motors)
162
189
  connections = data.get('connections', [])
163
190
  if not isinstance(connections, list) or len(connections) > MAX_CONNECTIONS:
164
191
  issue(problems, 'HOLD', 'CONNECTIONS_COUNT', 'connections', f'Maximum {MAX_CONNECTIONS} connections')
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "devagent-ignition"
7
- version = "0.1.6"
7
+ version = "0.1.8"
8
8
  description = "Offline industrial HMI engineering and Ignition Perspective candidate tools (production deployment not qualified)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13,<3.14"
@@ -1 +0,0 @@
1
- __version__ = '0.1.6'