rosotacom-dev 2.5.dev10__tar.gz → 2.5.dev12__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 (338) hide show
  1. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/PKG-INFO +6 -2
  2. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/README.md +5 -1
  3. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/cli.py +107 -14
  4. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom_dev.egg-info/PKG-INFO +6 -2
  5. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom_dev.egg-info/scm_version.json +2 -2
  6. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_cli.py +168 -5
  7. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.devcontainer/devcontainer.json.template +0 -0
  8. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.devcontainer/re_generate_devcontainer_json.py +0 -0
  9. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/CODEOWNERS +0 -0
  10. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
  11. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
  12. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
  13. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
  14. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
  15. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
  16. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
  17. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
  18. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  19. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/dependabot.yml +0 -0
  20. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/workflows/benchmark-calibrate.yml +0 -0
  21. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/workflows/benchmark-gate.yml +0 -0
  22. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/workflows/dev-release.yml +0 -0
  23. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/workflows/image-scan.yml +0 -0
  24. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/workflows/nightly-e2e.yml +0 -0
  25. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/workflows/pr-lightweight.yml +0 -0
  26. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/workflows/pr-merge-gate.yml +0 -0
  27. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.github/workflows/release.yml +0 -0
  28. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/.pre-commit-config.yaml +0 -0
  29. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/AGENTS.md +0 -0
  30. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/CONCURRENCY.md +0 -0
  31. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/CONTRIBUTING.md +0 -0
  32. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/DEVELOPMENT_PRINCIPLES.md +0 -0
  33. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/LICENSE.txt +0 -0
  34. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/MANIFEST.in +0 -0
  35. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/budgets.jsonl +0 -0
  36. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/calibration/README.md +0 -0
  37. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/calibration/capacity-size-tight-cyclone.json +0 -0
  38. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
  39. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/calibration/probe-loss-nominal-cyclone.json +0 -0
  40. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/calibration/probe-loss-tight-cyclone.json +0 -0
  41. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/calibration/probe-loss-tight-fastdds.json +0 -0
  42. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/calibration/probe-loss-tight-zenoh.json +0 -0
  43. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/codecov.yml +0 -0
  44. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/deployment-configuration.md +0 -0
  45. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/benchmark-ab.md +0 -0
  46. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/benchmark-bag-as-load.md +0 -0
  47. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/ci.md +0 -0
  48. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/ffmpeg-keyframes.md +0 -0
  49. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/findings/README.md +0 -0
  50. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
  51. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/findings/delay-alone-no-loss.md +0 -0
  52. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/findings/head-of-line-irregularity.md +0 -0
  53. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
  54. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/findings/lighter-message-loss.md +0 -0
  55. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
  56. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/forensics-report.md +0 -0
  57. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/geo-link-map.md +0 -0
  58. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/github-repository-settings.md +0 -0
  59. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/link-trace.md +0 -0
  60. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/owner-runbook.md +0 -0
  61. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/performance-bands.md +0 -0
  62. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/playbooks/README.md +0 -0
  63. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/quality-model.md +0 -0
  64. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/release-notes/TEMPLATE.md +0 -0
  65. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/release-notes/v2.1.md +0 -0
  66. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/release-notes/v2.2.md +0 -0
  67. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/release-notes/v2.3.md +0 -0
  68. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/release-notes/v2.4.md +0 -0
  69. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/release.md +0 -0
  70. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
  71. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/rfcs/0002-expectation-concepts.md +0 -0
  72. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/rfcs/0003-metric-backbone.md +0 -0
  73. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/rfcs/0004-network-profiles.md +0 -0
  74. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
  75. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/rfcs/0006-dynamic-qos.md +0 -0
  76. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/rfcs/0007-regression-gate.md +0 -0
  77. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/rfcs/README.md +0 -0
  78. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/testing.md +0 -0
  79. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/docs/work-items.md +0 -0
  80. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/install.sh +0 -0
  81. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/justfile +0 -0
  82. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/media/control_center.png +0 -0
  83. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/media/echo_test.png +0 -0
  84. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/media/forensics-report-example.png +0 -0
  85. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/media/host.png +0 -0
  86. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/media/vehicle.png +0 -0
  87. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/pyproject.toml +0 -0
  88. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/requirements.txt +0 -0
  89. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/rosotacom.yaml +0 -0
  90. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/run_session_in_container.py +0 -0
  91. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/session-configuration.md +0 -0
  92. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/setup.cfg +0 -0
  93. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/__init__.py +0 -0
  94. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/__main__.py +0 -0
  95. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/anonymize.py +0 -0
  96. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/bag_ground_truth.py +0 -0
  97. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/benched_set.py +0 -0
  98. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/benchmark.py +0 -0
  99. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/bundle_check.py +0 -0
  100. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/cli_benchmark.py +0 -0
  101. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/deployment.py +0 -0
  102. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/ffmpeg_packet.py +0 -0
  103. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/forensics.py +0 -0
  104. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/geomap.py +0 -0
  105. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/network_profiles.py +0 -0
  106. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/network_shaper.py +0 -0
  107. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/plots.py +0 -0
  108. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/py.typed +0 -0
  109. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/benched-set.yaml +0 -0
  110. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/.gitignore +0 -0
  111. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/README.md +0 -0
  112. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/__init__.py +0 -0
  113. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
  114. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
  115. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/profiles.yaml +0 -0
  116. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/ros2docker.json +0 -0
  117. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
  118. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
  119. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
  120. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
  121. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
  122. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
  123. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
  124. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
  125. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
  126. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
  127. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
  128. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
  129. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
  130. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
  131. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
  132. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
  133. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
  134. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
  135. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
  136. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
  137. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
  138. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
  139. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
  140. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
  141. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
  142. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
  143. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
  144. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
  145. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
  146. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
  147. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
  148. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
  149. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
  150. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
  151. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
  152. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
  153. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
  154. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
  155. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
  156. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
  157. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
  158. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
  159. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
  160. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
  161. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
  162. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
  163. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
  164. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
  165. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
  166. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
  167. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
  168. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
  169. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
  170. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
  171. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
  172. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
  173. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
  174. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
  175. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
  176. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
  177. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
  178. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
  179. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
  180. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
  181. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
  182. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
  183. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
  184. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
  185. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
  186. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
  187. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ros2docker.json.example +0 -0
  188. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
  189. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
  190. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
  191. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
  192. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
  193. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
  194. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
  195. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
  196. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
  197. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
  198. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
  199. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
  200. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
  201. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
  202. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
  203. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
  204. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
  205. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
  206. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
  207. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
  208. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
  209. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
  210. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
  211. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
  212. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
  213. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
  214. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
  215. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
  216. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
  217. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
  218. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
  219. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
  220. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
  221. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
  222. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
  223. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
  224. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
  225. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
  226. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
  227. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
  228. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
  229. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
  230. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
  231. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
  232. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
  233. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
  234. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
  235. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
  236. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
  237. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
  238. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
  239. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
  240. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
  241. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
  242. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
  243. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
  244. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
  245. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
  246. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
  247. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
  248. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
  249. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
  250. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
  251. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
  252. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
  253. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
  254. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
  255. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
  256. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
  257. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
  258. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
  259. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
  260. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
  261. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
  262. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
  263. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
  264. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
  265. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
  266. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +0 -0
  267. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
  268. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
  269. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
  270. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
  271. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
  272. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +0 -0
  273. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
  274. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
  275. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
  276. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/status_eval.py +0 -0
  277. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/stream_stats.py +0 -0
  278. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/trace_profiles.py +0 -0
  279. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/transit.py +0 -0
  280. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom/video_quality.py +0 -0
  281. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom_dev.egg-info/SOURCES.txt +0 -0
  282. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
  283. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
  284. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom_dev.egg-info/requires.txt +0 -0
  285. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom_dev.egg-info/scm_file_list.json +0 -0
  286. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
  287. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/stop_session_in_container.py +0 -0
  288. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/terminology.md +0 -0
  289. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_benched_set_registry.py +0 -0
  290. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_findings.py +0 -0
  291. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_markdown_links.py +0 -0
  292. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_ota_source_bundle.py +0 -0
  293. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_package_metadata.py +0 -0
  294. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_packaged_resources.py +0 -0
  295. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_profile_covers_generated_commands.py +0 -0
  296. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_pytest_policy.py +0 -0
  297. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_readme_examples.py +0 -0
  298. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_security_maintenance_config.py +0 -0
  299. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/contract/test_workflow_contracts.py +0 -0
  300. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/conftest.py +0 -0
  301. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/test_anonymize_e2e.py +0 -0
  302. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/test_benchmark_ab.py +0 -0
  303. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/test_benchmark_capacity.py +0 -0
  304. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/test_benchmark_replay.py +0 -0
  305. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/test_parallel_smoke.py +0 -0
  306. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/test_smoke.py +0 -0
  307. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/test_timeline_stepping.py +0 -0
  308. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/e2e/test_video_quality_e2e.py +0 -0
  309. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/sessions/generate_rmw_matrix.py +0 -0
  310. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
  311. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
  312. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
  313. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
  314. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
  315. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_anonymize.py +0 -0
  316. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_bag_ground_truth.py +0 -0
  317. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_benched_set.py +0 -0
  318. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_benchmark.py +0 -0
  319. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_bundle_check.py +0 -0
  320. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_cli_benchmark.py +0 -0
  321. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_concurrency.py +0 -0
  322. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_deployment.py +0 -0
  323. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_ffmpeg_packet.py +0 -0
  324. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_forensics.py +0 -0
  325. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_geomap.py +0 -0
  326. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_link_bytes.py +0 -0
  327. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_link_trace.py +0 -0
  328. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_network_profiles.py +0 -0
  329. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_network_shaper.py +0 -0
  330. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_ota_xml.py +0 -0
  331. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_plots.py +0 -0
  332. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_stage_latency.py +0 -0
  333. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_status_eval.py +0 -0
  334. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_status_overview.py +0 -0
  335. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_stream_stats.py +0 -0
  336. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_trace_profiles.py +0 -0
  337. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_transit.py +0 -0
  338. {rosotacom_dev-2.5.dev10 → rosotacom_dev-2.5.dev12}/tests/unit/test_video_quality.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rosotacom-dev
3
- Version: 2.5.dev10
3
+ Version: 2.5.dev12
4
4
  Summary: Host CLI for ROS OTA communication sessions.
5
5
  Author: develNor
6
6
  License-Expression: BSD-3-Clause
@@ -439,7 +439,11 @@ rosotacom ota-smoke 2_native_chatter \
439
439
 
440
440
  `ota-smoke` accepts sessions and scenarios. It puts rosotacom on each peer,
441
441
  stages the active project, runs delivery and isolation checks, collects
442
- artifacts, stops the run, and removes the remote workdir. Add `--interactive`
442
+ artifacts, stops the run, and removes the remote workdir. For scenario targets
443
+ the checks start only once every declared application container is running
444
+ (bounded at 10 minutes, covering a cold peer's first image build); an
445
+ application that never comes up fails the run by name instead of as missing
446
+ publishers. Add `--interactive`
443
447
  for a local control tmux with
444
448
  one attachable communication/catmux window per peer with a live status pane below
445
449
  each one. Scenario targets also get one native application-container window per
@@ -394,7 +394,11 @@ rosotacom ota-smoke 2_native_chatter \
394
394
 
395
395
  `ota-smoke` accepts sessions and scenarios. It puts rosotacom on each peer,
396
396
  stages the active project, runs delivery and isolation checks, collects
397
- artifacts, stops the run, and removes the remote workdir. Add `--interactive`
397
+ artifacts, stops the run, and removes the remote workdir. For scenario targets
398
+ the checks start only once every declared application container is running
399
+ (bounded at 10 minutes, covering a cold peer's first image build); an
400
+ application that never comes up fails the run by name instead of as missing
401
+ publishers. Add `--interactive`
398
402
  for a local control tmux with
399
403
  one attachable communication/catmux window per peer with a live status pane below
400
404
  each one. Scenario targets also get one native application-container window per
@@ -143,6 +143,10 @@ OTA_DEFAULT_SUDO_MODE = "passwordless"
143
143
  # meet this because they call an absolute path inside the workdir; checkout mode
144
144
  # calls the peer's own command by name, so it has to say where that lives.
145
145
  OTA_CHECKOUT_PATH_PREFIX = 'export PATH="$HOME/.local/bin:$PATH"; '
146
+ #: Set for a `--peer-exec` transport when the script it is about to run needs a
147
+ #: terminal on the far side. A transport that does not understand it is not
148
+ #: broken by it, which is why this is an environment variable and not a flag.
149
+ OTA_PEER_TTY_ENV = "ROSOTACOM_PEER_TTY"
146
150
 
147
151
  ws_creation_dir = WS_DIR / "session" / "creation"
148
152
  session_gen_path = ws_creation_dir / "generate_session_files.py"
@@ -1750,11 +1754,23 @@ def _ota_peer_target(peer: OtaSmokePeer) -> str:
1750
1754
  def _ota_remote_argv(peer: OtaSmokePeer, script: str, *, tty: bool = False, batch: bool = False) -> list[str]:
1751
1755
  # A named transport wins over the SSH alias, and it takes the script as its
1752
1756
  # last argument because that is the contract `ssh host <script>` already
1753
- # has. `tty` and `batch` are dropped on purpose rather than guessed at:
1754
- # they are options of one particular client, and a transport that is not
1755
- # ssh has no obligation to understand them.
1757
+ # has. `batch` is dropped rather than guessed at: it is an option of one
1758
+ # particular client, and a transport that is not ssh has no obligation to
1759
+ # understand it.
1760
+ #
1761
+ # `tty` is not droppable, and assuming it was cost a two-host run. The peer
1762
+ # windows start their container with `docker run -i -t`, which refuses
1763
+ # outright when the far side has no terminal — so a transport that cannot be
1764
+ # told "this one is interactive" can carry the probes and not the experiment.
1765
+ # It travels as an environment variable rather than an argument because the
1766
+ # argv contract is what makes any command usable here: a transport that
1767
+ # ignores the variable behaves exactly as before instead of failing on a
1768
+ # flag it never agreed to parse.
1756
1769
  if peer.exec_command:
1757
- return [*shlex.split(peer.exec_command), script]
1770
+ argv = shlex.split(peer.exec_command)
1771
+ if tty:
1772
+ argv = ["env", f"{OTA_PEER_TTY_ENV}=1", *argv]
1773
+ return [*argv, script]
1758
1774
  if peer.ssh:
1759
1775
  argv = ["ssh"]
1760
1776
  if batch:
@@ -3433,6 +3449,55 @@ def _ota_stop_peers(
3433
3449
  _ota_run(peer, command, label=f"{peer_name}: stop {target.name}", dry_run=dry_run, check=False)
3434
3450
 
3435
3451
 
3452
+ # How long verification waits for a scenario application container before it
3453
+ # gives up. Covers a first-run image build on a cold peer (observed ~3 min for
3454
+ # an apt-get install alone); the communication-container readiness wait uses
3455
+ # the same bound.
3456
+ OTA_SMOKE_APPLICATION_WAIT_TIMEOUT_S = 600
3457
+
3458
+
3459
+ def _ota_wait_for_scenario_applications(
3460
+ target: InteractiveSmokeTarget,
3461
+ plan: OtaSmokePlan,
3462
+ *,
3463
+ dry_run: bool,
3464
+ ) -> list[str]:
3465
+ """Block until every scenario application container declared for the target
3466
+ is running on its peer. The application windows start their container only
3467
+ after the peer's communication container is up, so on a cold machine the
3468
+ first check would otherwise run against applications that are still being
3469
+ built and report their absence as missing publishers (#218). A session
3470
+ target declares no applications and passes through untouched.
3471
+
3472
+ Running is deliberately the whole bound: whether an application *produces*
3473
+ is exactly what the session's own expectations then check."""
3474
+ definition = target.scenario_definition
3475
+ if definition is None:
3476
+ return []
3477
+ errors: list[str] = []
3478
+ for peer_name in sorted(plan.peers):
3479
+ peer = plan.peers[peer_name]
3480
+ for application in definition.applications.get(peer_name, ()):
3481
+ suffix = _sanitize_docker_name(f"_scenario_{target.name}_{peer_name}_{application.name}")
3482
+ label = f"{peer_name}: wait for application {application.name}"
3483
+ script = _ota_wait_for_running_container_suffix_script(
3484
+ suffix,
3485
+ f"{peer_name}:application:{application.name}",
3486
+ timeout_s=OTA_SMOKE_APPLICATION_WAIT_TIMEOUT_S,
3487
+ )
3488
+ result = _ota_run(peer, script, label=label, dry_run=dry_run, check=False)
3489
+ if result.returncode != 0:
3490
+ _ota_print_failure_output(label, result)
3491
+ errors.append(
3492
+ f"{peer_name}: application '{application.name}' has no running container after "
3493
+ f"{OTA_SMOKE_APPLICATION_WAIT_TIMEOUT_S}s; the scenario never came up, so its "
3494
+ "topics were not checked"
3495
+ )
3496
+ else:
3497
+ _print_completed_output(result)
3498
+ return errors
3499
+
3500
+
3436
3501
  def _ota_verify_only(args: argparse.Namespace) -> int:
3437
3502
  _runtime, plan, target = _resolve_ota_smoke_context(args)
3438
3503
  instance_id = getattr(args, "instance_id", None)
@@ -3440,6 +3505,11 @@ def _ota_verify_only(args: argparse.Namespace) -> int:
3440
3505
  raise RuntimeError("ota-smoke --verify-only requires --instance-id.")
3441
3506
  dry_run = bool(getattr(args, "dry_run", False))
3442
3507
  print(f"OTA smoke verification starting: {target.name} ({target.target_type}), instance={instance_id}")
3508
+ errors = _ota_wait_for_scenario_applications(target, plan, dry_run=dry_run)
3509
+ if errors:
3510
+ for error in errors:
3511
+ print(f"OTA SMOKE ERROR: {error}", file=sys.stderr)
3512
+ return 1
3443
3513
  print("OTA smoke: starting synthetic publishers where needed.")
3444
3514
  _ota_start_session_publishers(target, plan, dry_run=dry_run)
3445
3515
  errors = _ota_verify_delivery(target, plan, instance_id, dry_run=dry_run)
@@ -3452,15 +3522,35 @@ def _ota_verify_only(args: argparse.Namespace) -> int:
3452
3522
  return 0
3453
3523
 
3454
3524
 
3455
- def _ota_wait_for_running_container_suffix_script(suffix: str, label: str) -> str:
3525
+ def _ota_wait_for_running_container_suffix_script(suffix: str, label: str, timeout_s: int | None = None) -> str:
3456
3526
  pattern = shlex.quote(f"{re.escape(suffix)}$")
3457
3527
  quoted_label = shlex.quote(label)
3458
- return (
3459
- "container=''; "
3460
- f"until container=$(docker ps --filter status=running --format '{{{{.Names}}}}' "
3528
+ find_container = (
3529
+ f"container=$(docker ps --filter status=running --format '{{{{.Names}}}}' "
3461
3530
  f"| grep -E {pattern} | head -n 1) "
3462
- '&& [ -n "$container" ]; do '
3463
- f"echo '[INFO] waiting for running container:' {quoted_label}; "
3531
+ '&& [ -n "$container" ]'
3532
+ )
3533
+ if timeout_s is None:
3534
+ return (
3535
+ "container=''; "
3536
+ f"until {find_container}; do "
3537
+ f"echo '[INFO] waiting for running container:' {quoted_label}; "
3538
+ "sleep 2; "
3539
+ "done; "
3540
+ 'echo "[INFO] found running container: $container"'
3541
+ )
3542
+ # Bounded variant for captured (non-interactive) callers: one line up front
3543
+ # instead of a poll-cadence echo, and a hard failure when the bound is hit.
3544
+ attempts = max(1, int(timeout_s) // 2)
3545
+ return (
3546
+ f"echo '[INFO] waiting up to {int(timeout_s)}s for running container:' {quoted_label}; "
3547
+ "container=''; tries=0; "
3548
+ f"until {find_container}; do "
3549
+ "tries=$((tries+1)); "
3550
+ f'if [ "$tries" -ge {attempts} ]; then '
3551
+ f"echo '[ERROR] no running container after {int(timeout_s)}s:' {quoted_label} >&2; "
3552
+ "exit 1; "
3553
+ "fi; "
3464
3554
  "sleep 2; "
3465
3555
  "done; "
3466
3556
  'echo "[INFO] found running container: $container"'
@@ -3534,7 +3624,7 @@ def _ota_create_tmux(
3534
3624
  session_name,
3535
3625
  "-n",
3536
3626
  _safe_path_token(f"{first_peer.name}_communication"),
3537
- _ota_quote_cmd(_ota_remote_argv(first_peer, first_script, tty=bool(first_peer.ssh))),
3627
+ _ota_quote_cmd(_ota_remote_argv(first_peer, first_script, tty=_ota_peer_is_remote(first_peer))),
3538
3628
  ),
3539
3629
  text=True,
3540
3630
  capture_output=True,
@@ -3614,7 +3704,7 @@ def _ota_create_tmux(
3614
3704
  session_name,
3615
3705
  "-n",
3616
3706
  _safe_path_token(f"{peer.name}_communication"),
3617
- _ota_quote_cmd(_ota_remote_argv(peer, script, tty=bool(peer.ssh))),
3707
+ _ota_quote_cmd(_ota_remote_argv(peer, script, tty=_ota_peer_is_remote(peer))),
3618
3708
  ),
3619
3709
  text=True,
3620
3710
  capture_output=True,
@@ -3645,7 +3735,7 @@ def _ota_create_tmux(
3645
3735
  session_name,
3646
3736
  "-n",
3647
3737
  _safe_path_token(f"{peer.name}_{application.name}"),
3648
- _ota_quote_cmd(_ota_remote_argv(peer, application_script, tty=bool(peer.ssh))),
3738
+ _ota_quote_cmd(_ota_remote_argv(peer, application_script, tty=_ota_peer_is_remote(peer))),
3649
3739
  ),
3650
3740
  text=True,
3651
3741
  capture_output=True,
@@ -3810,7 +3900,7 @@ def _start_interactive_ota_smoke(args: argparse.Namespace) -> int:
3810
3900
  if target.target_type == "scenario":
3811
3901
  for peer_name, peer in plan.peers.items():
3812
3902
  attach = _ota_rosotacom_command(plan, ["scenario", "attach", target.name, "--identity", peer_name], peer)
3813
- attach_cmd = _ota_quote_cmd(_ota_remote_argv(peer, attach, tty=bool(peer.ssh)))
3903
+ attach_cmd = _ota_quote_cmd(_ota_remote_argv(peer, attach, tty=_ota_peer_is_remote(peer)))
3814
3904
  print(f"Manual remote scenario reattach for {peer_name}: {attach_cmd}")
3815
3905
  if mode == "attach":
3816
3906
  subprocess.run(_tmux_command(runtime, "attach-session", "-t", created), check=True)
@@ -3866,6 +3956,9 @@ def _start_noninteractive_ota_smoke(args: argparse.Namespace) -> int:
3866
3956
  )
3867
3957
  if not dry_run:
3868
3958
  time.sleep(12)
3959
+ wait_errors = _ota_wait_for_scenario_applications(target, plan, dry_run=dry_run)
3960
+ if wait_errors:
3961
+ raise RuntimeError("OTA smoke verification failed:\n - " + "\n - ".join(wait_errors))
3869
3962
  _ota_start_session_publishers(target, plan, dry_run=dry_run)
3870
3963
  errors += _ota_verify_delivery(target, plan, instance.instance_id, dry_run=dry_run, profile=profile_name)
3871
3964
  errors += _ota_verify_isolation(target, plan, dry_run=dry_run)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rosotacom-dev
3
- Version: 2.5.dev10
3
+ Version: 2.5.dev12
4
4
  Summary: Host CLI for ROS OTA communication sessions.
5
5
  Author: develNor
6
6
  License-Expression: BSD-3-Clause
@@ -439,7 +439,11 @@ rosotacom ota-smoke 2_native_chatter \
439
439
 
440
440
  `ota-smoke` accepts sessions and scenarios. It puts rosotacom on each peer,
441
441
  stages the active project, runs delivery and isolation checks, collects
442
- artifacts, stops the run, and removes the remote workdir. Add `--interactive`
442
+ artifacts, stops the run, and removes the remote workdir. For scenario targets
443
+ the checks start only once every declared application container is running
444
+ (bounded at 10 minutes, covering a cold peer's first image build); an
445
+ application that never comes up fails the run by name instead of as missing
446
+ publishers. Add `--interactive`
443
447
  for a local control tmux with
444
448
  one attachable communication/catmux window per peer with a live status pane below
445
449
  each one. Scenario targets also get one native application-container window per
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "tag": "2.4",
3
- "distance": 10,
4
- "node": "gc0c857f77e0a3a0b17134fdc9e0edb7a70f80a1b",
3
+ "distance": 12,
4
+ "node": "g7fbd637414233d05a477855064bbe723a0e9a36b",
5
5
  "dirty": false,
6
6
  "branch": "HEAD",
7
7
  "node_date": "2026-08-11"
@@ -982,6 +982,133 @@ def test_ota_collect_logs_extracts_each_peer_into_instance(
982
982
  assert not list(host_dir.glob("**/*.tar.gz.b64"))
983
983
 
984
984
 
985
+ def _wait_script_env(tmp_path: Path, docker_stdout: str) -> dict[str, str]:
986
+ """PATH with a stub docker that prints `docker_stdout` for any invocation."""
987
+ stub = tmp_path / "bin" / "docker"
988
+ stub.parent.mkdir(exist_ok=True)
989
+ stub.write_text(f"#!/bin/sh\nprintf '%s\\n' {rosotacom.shlex.quote(docker_stdout)}\n", encoding="utf-8")
990
+ stub.chmod(0o755)
991
+ return {**os.environ, "PATH": f"{stub.parent}:{os.environ['PATH']}"}
992
+
993
+
994
+ def test_ota_wait_script_is_unbounded_without_timeout() -> None:
995
+ script = rosotacom._ota_wait_for_running_container_suffix_script("_com_to_b", "a:communication")
996
+
997
+ assert "exit 1" not in script
998
+ assert "waiting for running container:" in script
999
+
1000
+
1001
+ def test_ota_bounded_wait_script_fails_clearly_when_the_bound_is_hit(tmp_path: Path) -> None:
1002
+ script = rosotacom._ota_wait_for_running_container_suffix_script(
1003
+ "_scenario_demo_a_local_app", "a:application:local_app", timeout_s=2
1004
+ )
1005
+
1006
+ result = subprocess.run(
1007
+ ["bash", "-c", script], env=_wait_script_env(tmp_path, "unrelated_container"), text=True, capture_output=True
1008
+ )
1009
+
1010
+ assert result.returncode == 1
1011
+ assert "[ERROR] no running container after 2s: a:application:local_app" in result.stderr
1012
+
1013
+
1014
+ def test_ota_bounded_wait_script_succeeds_once_the_container_runs(tmp_path: Path) -> None:
1015
+ script = rosotacom._ota_wait_for_running_container_suffix_script(
1016
+ "_scenario_demo_a_local_app", "a:application:local_app", timeout_s=2
1017
+ )
1018
+ runtime, _resolved = _write_test_scenario_project(tmp_path)
1019
+ container = rosotacom._scenario_container_name(runtime, "demo", "a", "local_app", "run1")
1020
+
1021
+ result = subprocess.run(
1022
+ ["bash", "-c", script], env=_wait_script_env(tmp_path, container), text=True, capture_output=True
1023
+ )
1024
+
1025
+ assert result.returncode == 0
1026
+ assert f"[INFO] found running container: {container}" in result.stdout
1027
+
1028
+
1029
+ def test_ota_wait_for_scenario_applications_waits_per_declared_application(
1030
+ tmp_path: Path,
1031
+ monkeypatch: pytest.MonkeyPatch,
1032
+ ) -> None:
1033
+ runtime, _resolved = _write_test_scenario_project(tmp_path)
1034
+ target = rosotacom._resolve_interactive_smoke_target("demo", runtime, "scenario")
1035
+ plan = _ota_plan(tmp_path)
1036
+ ran: list[tuple[str, str]] = []
1037
+
1038
+ def fake_ota_run(peer: rosotacom.OtaSmokePeer, script: str, **_kwargs: object) -> subprocess.CompletedProcess[str]:
1039
+ ran.append((peer.name, script))
1040
+ return subprocess.CompletedProcess([], 0, "", "")
1041
+
1042
+ monkeypatch.setattr(rosotacom, "_ota_run", fake_ota_run)
1043
+
1044
+ assert rosotacom._ota_wait_for_scenario_applications(target, plan, dry_run=False) == []
1045
+
1046
+ assert [name for name, _script in ran] == ["a", "b"]
1047
+ for identity, script in ran:
1048
+ assert f"_scenario_demo_{identity}_local_app" in script
1049
+ # The bound: verification must not wait forever, unlike the interactive panes.
1050
+ assert "exit 1" in script
1051
+
1052
+
1053
+ def test_ota_wait_for_scenario_applications_reports_the_bound_not_the_topics(
1054
+ tmp_path: Path,
1055
+ monkeypatch: pytest.MonkeyPatch,
1056
+ ) -> None:
1057
+ runtime, _resolved = _write_test_scenario_project(tmp_path)
1058
+ target = rosotacom._resolve_interactive_smoke_target("demo", runtime, "scenario")
1059
+ plan = _ota_plan(tmp_path)
1060
+
1061
+ monkeypatch.setattr(
1062
+ rosotacom,
1063
+ "_ota_run",
1064
+ lambda peer, script, **kwargs: subprocess.CompletedProcess([], 0 if peer.name == "a" else 1, "", ""),
1065
+ )
1066
+
1067
+ errors = rosotacom._ota_wait_for_scenario_applications(target, plan, dry_run=False)
1068
+
1069
+ assert len(errors) == 1
1070
+ assert "b: application 'local_app' has no running container" in errors[0]
1071
+ assert "never came up" in errors[0]
1072
+
1073
+
1074
+ def test_ota_verify_only_stops_before_checks_when_applications_never_come_up(
1075
+ tmp_path: Path,
1076
+ monkeypatch: pytest.MonkeyPatch,
1077
+ ) -> None:
1078
+ runtime, _resolved = _write_test_scenario_project(tmp_path)
1079
+ target = rosotacom._resolve_interactive_smoke_target("demo", runtime, "scenario")
1080
+ plan = _ota_plan(tmp_path)
1081
+ checks: list[str] = []
1082
+
1083
+ monkeypatch.setattr(rosotacom, "_resolve_ota_smoke_context", lambda args: (runtime, plan, target))
1084
+ monkeypatch.setattr(
1085
+ rosotacom,
1086
+ "_ota_wait_for_scenario_applications",
1087
+ lambda *args, **kwargs: ["b: application 'local_app' has no running container after 600s"],
1088
+ )
1089
+ monkeypatch.setattr(rosotacom, "_ota_start_session_publishers", lambda *args, **kwargs: checks.append("publishers"))
1090
+ monkeypatch.setattr(rosotacom, "_ota_verify_delivery", lambda *args, **kwargs: checks.append("delivery") or [])
1091
+ monkeypatch.setattr(rosotacom, "_ota_verify_isolation", lambda *args, **kwargs: checks.append("isolation") or [])
1092
+
1093
+ rc = rosotacom._ota_verify_only(argparse.Namespace(instance_id="run1", dry_run=False))
1094
+
1095
+ assert rc == 1
1096
+ # The point of #218: no status checks against a scenario that is not up.
1097
+ assert checks == []
1098
+
1099
+
1100
+ def test_ota_wait_for_scenario_applications_ignores_session_targets(
1101
+ tmp_path: Path,
1102
+ monkeypatch: pytest.MonkeyPatch,
1103
+ ) -> None:
1104
+ runtime, _resolved = _write_test_scenario_project(tmp_path)
1105
+ target = rosotacom._resolve_interactive_smoke_target("demo", runtime, "session")
1106
+ plan = _ota_plan(tmp_path)
1107
+ monkeypatch.setattr(rosotacom, "_ota_run", lambda *args, **kwargs: pytest.fail("session targets must not wait"))
1108
+
1109
+ assert rosotacom._ota_wait_for_scenario_applications(target, plan, dry_run=False) == []
1110
+
1111
+
985
1112
  def test_ota_smoke_parser_accepts_stop_without_peer_arguments(monkeypatch: pytest.MonkeyPatch) -> None:
986
1113
  calls: list[argparse.Namespace] = []
987
1114
  monkeypatch.setattr(rosotacom, "ota_smoke", lambda args: calls.append(args) or 0)
@@ -1076,6 +1203,9 @@ def test_noninteractive_ota_smoke_lifecycle_uses_generic_runner(
1076
1203
  monkeypatch.setattr(rosotacom, "_ota_preflight", lambda *args, **kwargs: calls.append("preflight"))
1077
1204
  monkeypatch.setattr(rosotacom, "_ota_prepare_hosts", lambda *args, **kwargs: calls.append("prepare"))
1078
1205
  monkeypatch.setattr(rosotacom, "_ota_start_peers", lambda *args, **kwargs: calls.append("start"))
1206
+ monkeypatch.setattr(
1207
+ rosotacom, "_ota_wait_for_scenario_applications", lambda *args, **kwargs: calls.append("wait-apps") or []
1208
+ )
1079
1209
  monkeypatch.setattr(rosotacom, "_ota_start_session_publishers", lambda *args, **kwargs: calls.append("publishers"))
1080
1210
  monkeypatch.setattr(rosotacom, "_ota_verify_delivery", lambda *args, **kwargs: calls.append("test") or [])
1081
1211
  monkeypatch.setattr(rosotacom, "_ota_verify_isolation", lambda *args, **kwargs: calls.append("isolation") or [])
@@ -1104,6 +1234,7 @@ def test_noninteractive_ota_smoke_lifecycle_uses_generic_runner(
1104
1234
  "prepare",
1105
1235
  "start",
1106
1236
  "sleep:12",
1237
+ "wait-apps",
1107
1238
  "publishers",
1108
1239
  "test",
1109
1240
  "isolation",
@@ -1161,6 +1292,8 @@ def test_ota_smoke_dry_run_exercises_generic_remote_flow(
1161
1292
  assert "b: reachable: running remote command" in out
1162
1293
  assert "a: start demo: running remote command" in out
1163
1294
  assert "b: start demo: running remote command" in out
1295
+ assert "a: wait for application local_app: running remote command" in out
1296
+ assert "b: wait for application local_app: running remote command" in out
1164
1297
  assert "a: rosotacom test: running remote command" in out
1165
1298
  assert "a: publish isolation probe: running remote command" in out
1166
1299
  assert "b: check isolation probe absent: running remote command" in out
@@ -3245,19 +3378,49 @@ def test_ota_peer_exec_replaces_the_ssh_client(tmp_path: Path) -> None:
3245
3378
  ]
3246
3379
 
3247
3380
 
3248
- def test_ota_peer_exec_ignores_options_that_belong_to_ssh(tmp_path: Path) -> None:
3249
- # `-t` and `-o BatchMode=yes` are options of one client. Passing them to an
3250
- # arbitrary transport would be guessing at an interface it never agreed to,
3251
- # and the failure would look like a broken peer rather than a wrong flag.
3381
+ def test_ota_peer_exec_ignores_batch_mode_which_belongs_to_ssh(tmp_path: Path) -> None:
3382
+ # `-o BatchMode=yes` is an option of one client. Passing it to an arbitrary
3383
+ # transport would be guessing at an interface it never agreed to, and the
3384
+ # failure would look like a broken peer rather than a wrong flag.
3385
+ plan = _ota_exec_plan(_write_checkout_project(tmp_path))
3386
+
3387
+ assert rosotacom._ota_remote_argv(plan.peers["a"], "true", batch=True) == [
3388
+ "remote-rosotacom",
3389
+ "majestic-tks",
3390
+ "true",
3391
+ ]
3392
+
3393
+
3394
+ def test_ota_peer_exec_carries_the_tty_request(tmp_path: Path) -> None:
3395
+ # Dropping this cost a two-host run: the peer windows start their container
3396
+ # with `docker run -i -t`, which refuses outright when the far side has no
3397
+ # terminal, so a transport that cannot be told "this one is interactive"
3398
+ # carries the probes and not the experiment.
3252
3399
  plan = _ota_exec_plan(_write_checkout_project(tmp_path))
3253
3400
 
3254
- assert rosotacom._ota_remote_argv(plan.peers["a"], "true", tty=True, batch=True) == [
3401
+ assert rosotacom._ota_remote_argv(plan.peers["a"], "true", tty=True) == [
3402
+ "env",
3403
+ "ROSOTACOM_PEER_TTY=1",
3255
3404
  "remote-rosotacom",
3256
3405
  "majestic-tks",
3257
3406
  "true",
3258
3407
  ]
3259
3408
 
3260
3409
 
3410
+ def test_ota_peer_exec_tty_is_a_variable_so_an_older_transport_still_works(
3411
+ tmp_path: Path,
3412
+ ) -> None:
3413
+ # An environment variable rather than a flag, so a transport that does not
3414
+ # understand it behaves exactly as before instead of dying on an argument it
3415
+ # never agreed to parse. The argv contract is what makes any command usable
3416
+ # as a transport at all.
3417
+ plan = _ota_exec_plan(_write_checkout_project(tmp_path))
3418
+ argv = rosotacom._ota_remote_argv(plan.peers["a"], "true", tty=True)
3419
+
3420
+ assert argv[-1] == "true"
3421
+ assert not any(part.startswith("-") for part in argv)
3422
+
3423
+
3261
3424
  def test_ota_peer_exec_makes_a_peer_remote(tmp_path: Path) -> None:
3262
3425
  # Everything that used to ask `peer.ssh` meant "is it over there". A peer
3263
3426
  # behind a command transport is, and a caller that still reads `.ssh` would