topicforge 0.2.0__tar.gz → 0.3.0__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 (70) hide show
  1. {topicforge-0.2.0 → topicforge-0.3.0}/.gitignore +5 -0
  2. {topicforge-0.2.0 → topicforge-0.3.0}/CHANGELOG.md +47 -5
  3. {topicforge-0.2.0 → topicforge-0.3.0}/PKG-INFO +41 -13
  4. {topicforge-0.2.0 → topicforge-0.3.0}/README.md +34 -12
  5. topicforge-0.3.0/docs/DDS_QUICKSTART.md +156 -0
  6. topicforge-0.3.0/docs/MIGRATION_v0.2_to_v0.3.md +153 -0
  7. topicforge-0.3.0/docs/dds-interop-matrix.md +50 -0
  8. {topicforge-0.2.0 → topicforge-0.3.0}/docs/product-plan.md +3 -3
  9. {topicforge-0.2.0 → topicforge-0.3.0}/pyproject.toml +16 -3
  10. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/__init__.py +1 -1
  11. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/base.py +3 -1
  12. topicforge-0.3.0/src/topicforge/adapters/common/__init__.py +17 -0
  13. topicforge-0.3.0/src/topicforge/adapters/common/dds_helpers.py +111 -0
  14. topicforge-0.3.0/src/topicforge/adapters/dds_cyclone/adapter.py +384 -0
  15. topicforge-0.3.0/src/topicforge/adapters/dds_fast/__init__.py +11 -0
  16. topicforge-0.3.0/src/topicforge/adapters/dds_fast/adapter.py +493 -0
  17. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_live/adapter.py +6 -3
  18. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_mock/fixtures.py +10 -0
  19. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/config/settings.py +19 -8
  20. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/models/schemas.py +16 -7
  21. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/services/factory.py +51 -17
  22. topicforge-0.3.0/src/topicforge/services/health.py +65 -0
  23. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/services/inspector.py +32 -6
  24. topicforge-0.3.0/tests/test_config.py +170 -0
  25. topicforge-0.3.0/tests/test_cyclone_adapter.py +117 -0
  26. topicforge-0.3.0/tests/test_dds_cross_vendor.py +136 -0
  27. topicforge-0.3.0/tests/test_dds_helpers.py +117 -0
  28. topicforge-0.3.0/tests/test_fast_adapter.py +146 -0
  29. topicforge-0.3.0/tests/test_health.py +126 -0
  30. {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_qos_analyzer.py +108 -1
  31. topicforge-0.2.0/docs/DDS_QUICKSTART.md +0 -111
  32. topicforge-0.2.0/docs/v0.1.2-action-plan.md +0 -356
  33. topicforge-0.2.0/src/topicforge/adapters/common/__init__.py +0 -5
  34. topicforge-0.2.0/src/topicforge/adapters/dds_cyclone/adapter.py +0 -110
  35. topicforge-0.2.0/src/topicforge/services/health.py +0 -32
  36. topicforge-0.2.0/tests/test_config.py +0 -58
  37. topicforge-0.2.0/tests/test_cyclone_adapter.py +0 -56
  38. topicforge-0.2.0/tests/test_health.py +0 -56
  39. {topicforge-0.2.0 → topicforge-0.3.0}/LICENSE +0 -0
  40. {topicforge-0.2.0 → topicforge-0.3.0}/docs/MIGRATION_v0.1_to_v0.2.md +0 -0
  41. {topicforge-0.2.0 → topicforge-0.3.0}/docs/TESTING.md +0 -0
  42. {topicforge-0.2.0 → topicforge-0.3.0}/docs/pro.md +0 -0
  43. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/__main__.py +0 -0
  44. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/__init__.py +0 -0
  45. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/common/qos_analyzer.py +0 -0
  46. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/dds_cyclone/__init__.py +0 -0
  47. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_live/__init__.py +0 -0
  48. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_mock/__init__.py +0 -0
  49. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_mock/adapter.py +0 -0
  50. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/config/__init__.py +0 -0
  51. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/models/__init__.py +0 -0
  52. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/server/__init__.py +0 -0
  53. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/server/app.py +0 -0
  54. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/services/__init__.py +0 -0
  55. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/services/constants.py +0 -0
  56. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/telemetry/__init__.py +0 -0
  57. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/telemetry/client.py +0 -0
  58. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/tools/__init__.py +0 -0
  59. {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/tools/handlers.py +0 -0
  60. {topicforge-0.2.0 → topicforge-0.3.0}/tests/__init__.py +0 -0
  61. {topicforge-0.2.0 → topicforge-0.3.0}/tests/conftest.py +0 -0
  62. {topicforge-0.2.0 → topicforge-0.3.0}/tests/fixtures/csv_echo_imu.txt +0 -0
  63. {topicforge-0.2.0 → topicforge-0.3.0}/tests/fixtures/csv_echo_pose_multi.txt +0 -0
  64. {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_dds_schemas.py +0 -0
  65. {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_inspector.py +0 -0
  66. {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_live_adapter_parse.py +0 -0
  67. {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_live_adapter_subprocess.py +0 -0
  68. {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_mock_adapter.py +0 -0
  69. {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_telemetry.py +0 -0
  70. {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_tools_integration.py +0 -0
@@ -212,6 +212,11 @@ CLAUDE*.md
212
212
  # decisions are bisectable per release.
213
213
  !/docs/projet-file/*-audit-*.md
214
214
  !/docs/projet-file/audit-*.md
215
+ # External reference material (OMG interop reports, third-party specs
216
+ # snapshots) the maintainer wants pinned in git so strategy decisions
217
+ # remain reproducible. Tracked, not part of sdist.
218
+ !/docs/projet-file/references/
219
+ !/docs/projet-file/references/**
215
220
  /docs/assets/screencast-raw/
216
221
 
217
222
 
@@ -7,11 +7,52 @@ and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2026-05-14
11
+
12
+ ### Strategic
13
+
14
+ - **OMG DDS-RTPS multi-vendor positioning.** TopicForge is now framed as a read-only DDS-RTPS observer that joins the bus via one of two OSS Python participants — Eclipse CycloneDDS or eProsima Fast DDS — and observes every conformant vendor on the domain (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, etc.) regardless of host language. See `docs/dds-interop-matrix.md` for the canonical statement and `docs/projet-file/references/omg-dds-interop-2025-05-08.xlsx` for the OMG May 2025 interop reference. The earlier v0.2.0/v0.3.0 phasing (Cyclone-only at v0.3.0, RTI at v0.3.0+) is collapsed: multi-vendor OSS lands together at v0.3.0 ; RTI Pro defers to v0.4.0+.
15
+
16
+ ### Added
17
+
18
+ - **Real `CycloneDdsAdapter`** — replaces the v0.2.0 stub with actual CycloneDDS discovery via `cyclonedds.builtin.BuiltinDataReader` on the DCPS participant/subscription/publication builtin topics. QoS extracted via `Policy.*` class-name introspection. `take_iter(timeout=...)` for bounded discovery. Lazy-imported via `services.factory`.
19
+ - **`FastDdsAdapter`** (`adapters/dds_fast/`) — new parallel OSS adapter built on the `fastdds` Python bindings (BSD-licensed, eProsima). Duck-typed listener subclass aggregates discovery callbacks under an RLock. Bounded `discovery_wait_ms=1500` warm-up after participant creation. `close()` releases the participant via `factory.delete_participant`.
20
+ - **`adapters/common/dds_helpers.py`** — vendor-neutral helpers: `canonicalize_vendor_id` (OMG vendor_id → canonical tag), `format_guid` (16-byte GUID → `xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx` canonical text), `DDS_ONLY_ERROR_MSG` (shared remediation message). Pure functions, no DDS dependency.
21
+ - **Pyproject extras refactor**: `[dds-cyclone]` (Cyclone only), `[dds-fast]` (Fast only), `[dds]` (both — union of v0.2.0 `[dds]` behavior plus fastdds).
22
+ - **`TOPICFORGE_DDS_BACKEND=fast`** — new accepted value alongside `mock | cyclone | rti | auto`.
23
+ - **3rd mock participant** with `vendor="fast"` exercises the multi-vendor positioning in mock mode.
24
+ - **New pytest marker** `requires_fastdds` — auto-skips without the binding.
25
+ - **35+ new tests**: `tests/test_dds_helpers.py`, `tests/test_fast_adapter.py`, `tests/test_dds_cross_vendor.py` (parametrized on both adapters), 6 analyzer edge cases in `tests/test_qos_analyzer.py`, 4 new health tests for DDS field population.
26
+
27
+ ### Changed
28
+
29
+ - **`ParticipantInfo.vendor` Literal widened** to include `"fast"`. **Strict JSON-schema clients pinned to v0.2.0 will reject `vendor:fast` unless their schema is regenerated.** Standard MCP clients reading tool descriptions dynamically are unaffected.
30
+ - **`HealthReport.dds_backend` Literal widened** to include `"fast"`. Same soft-breaking caveat.
31
+ - **`AdapterName` Literal widened** to include `"fast"` (internal type — no wire impact).
32
+ - **`DdsBackend` / `ResolvedDdsBackend`** widened to include `"fast"`.
33
+ - **`Settings.effective_dds_backend` auto resolution** now prefers Fast DDS > Cyclone DDS > Mock (was Cyclone > Mock in v0.2.0). v0.2.0 users with only `cyclonedds` installed see no change — Fast is unimportable on their host. Users with both SDKs installed will see Fast selected. Reflects the OMG May 2025 interop matrix.
34
+ - **`HealthService.report()`** now populates `dds_backend`, `dds_domain_id`, `middleware_available` — previously returned schema defaults regardless of configuration (v0.2.0 latent bug). `middleware_available` is checked via `importlib.util.find_spec` on the active backend's Python module.
35
+ - **`Ros2CliAdapter._DDS_MODULE_INACTIVE_MSG`** updated to mention both `pip install topicforge[dds-cyclone]` and `pip install topicforge[dds-fast]` remediation paths.
36
+ - **`Inspector` DDS topic validator relaxed** — `detect_qos_mismatches` and `peek_dds_samples` now accept DDS-native topic names (no leading `/` required, `::` separators allowed) via a new `_validate_topic_name_dds`. The strict ROS2 validator stays in place for the 5 ROS2 graph methods. Resolves audit-2026-05-14 "Refactor opportunities" #5.
37
+
38
+ ### Removed
39
+
40
+ - **`CycloneDdsAdapter` v0.2.0 stub** — `_NOT_IMPLEMENTED_MSG` and the corresponding `test_dds_surface_raises_stub_error_in_v020` test removed. The 3 DDS methods now serve real results when cyclonedds is installed.
41
+
42
+ ### Notes
43
+
44
+ - **OMG-DDS-RTPS interoperability** is the protocol guarantee that makes multi-vendor observation work — see `docs/dds-interop-matrix.md` and `docs/projet-file/references/omg-dds-interop-2025-05-08.xlsx`.
45
+ - **v0.3.0 `peek_dds_samples` limitation** — full-fidelity on the 4 builtin DCPS topics (`DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`) ; arbitrary user topics raise an `AdapterError` with a v0.3.x roadmap pointer (XTypes/IDL discovery is the missing piece, both for Cyclone via `cyclonedds.dynamic.get_types_for_typeid` and for Fast DDS via XTypes remote type lookup).
46
+ - **`pip install topicforge[dds]` in v0.3.0** now pulls BOTH `cyclonedds` and `fastdds` (was Cyclone only in v0.2.0). Use `[dds-cyclone]` or `[dds-fast]` for single-vendor installs. See `docs/MIGRATION_v0.2_to_v0.3.md`.
47
+ - **Fast DDS pin**: `fastdds>=2.6.1,<3` — Fast DDS 3.x binding wheels for Python 3.11+ on Windows / Linux are not yet stable. Bump when upstream cuts stable 3.x wheels.
48
+ - **No code change to the 5 ROS2 tools** — `health_check`, `list_topics`, `get_topic_info`, `sample_messages`, `analyze_bag` behave identically to v0.2.0. The `mode_effective` wire contract is unchanged ; `health_check` now populates DDS fields correctly.
49
+ - **Full migration guide**: `docs/MIGRATION_v0.2_to_v0.3.md`.
50
+
10
51
  ## [0.2.0] - 2026-05-14
11
52
 
12
53
  ### Strategic
13
54
 
14
- - **Mono-MCP pivot (2026-05-14).** The 3-to-5-MCP pack draft is collapsed into a 2-product strategy: TopicForge umbrella (this product — covers ROS2 today and grows a DDS observability module starting with v0.2.0), and **DatasetForge** (Vision Dataset Inspector, the standalone second product). DdsForge as a standalone repo is cancelled — its spec is reframed as the TopicForge DDS module spec at `docs/projet-file/mcp-02-spec.md`. Motif: solo-maintenance cost of two parallel repos was the binding constraint, and ROS2 / DDS are the same problem shape (typed pub/sub graph introspection) under the same `MiddlewareAdapter` superset.
55
+ - **Mono-MCP pivot (2026-05-14).** The 3-to-5-MCP pack draft is collapsed into a 2-product strategy: TopicForge umbrella (this product — covers ROS2 today and grows a DDS observability module starting with v0.2.0), and **DatasetForge** (Vision Dataset Inspector, the standalone second product). The previously-planned standalone DDS-MCP product is cancelled — its spec is reframed as the TopicForge DDS module spec at `docs/projet-file/mcp-02-spec.md`. Motif: solo-maintenance cost of two parallel repos was the binding constraint, and ROS2 / DDS are the same problem shape (typed pub/sub graph introspection) under the same `MiddlewareAdapter` superset.
15
56
 
16
57
  ### Added
17
58
 
@@ -54,12 +95,12 @@ and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/
54
95
  ### Added
55
96
 
56
97
  - **`mode_effective` on every tool response (schema, soft-breaking additive).** `TopicInfo`, `SampleResult`, and `BagAnalysis` now carry a required `mode_effective: Literal["mock", "live"]` field. A new `effective_mode` property on the `RosAdapter` protocol is the single source of truth; `Ros2CliAdapter` returns `"live"`, `MockAdapter` returns `"mock"`, services thread it through at result construction time. **Producer side**: Python code constructing these models directly must now supply `mode_effective` — models are `frozen=True, extra="forbid"` with no default. **Client side (over MCP)**: additive — an MCP client consuming JSON sees one extra key per response and is unaffected unless it strictly validates against the v0.1.1 schema with a no-extra-keys assumption.
57
- - **DdsForge spec** (`docs/projet-file/mcp-02-spec.md`). Strategic draft for MCP 02: safety-first read-only DDS observability across middleware vendors (CycloneDDS OSS, RTI Connext Pro tier). Five tools, `MiddlewareAdapter` protocol, mock + cyclone + rti + auto modes. Reviewer notes appended (2026-05-13): wrong cross-reference in §11 flagged.
58
- - **DatasetForge spec** (`docs/projet-file/mcp-03-spec.md`). Vision Dataset Inspector spec, re-slotted to MCP 03 after competitive-landscape audit that surfaced zero non-ROS DDS-MCP projects and made DdsForge the stronger MCP 02 candidate. Reviewer notes appended (2026-05-13): contradictory §11 phrasing and two implicitly-resolved open questions flagged.
98
+ - **DDS-MCP spec** (`docs/projet-file/mcp-02-spec.md`). Strategic draft for MCP 02 at the time: safety-first read-only DDS observability across middleware vendors (CycloneDDS OSS, RTI Connext Pro tier). Five tools, `MiddlewareAdapter` protocol, mock + cyclone + rti + auto modes. Reviewer notes appended (2026-05-13): wrong cross-reference in §11 flagged. (Reframed the next day as a TopicForge module after the mono-MCP pivot — see [0.2.0] Strategic section.)
99
+ - **DatasetForge spec** (`docs/projet-file/mcp-03-spec.md`). Vision Dataset Inspector spec, re-slotted to MCP 03 after competitive-landscape audit that surfaced zero non-ROS DDS-MCP projects and made a standalone DDS-MCP the stronger MCP 02 candidate. Reviewer notes appended (2026-05-13): contradictory §11 phrasing and two implicitly-resolved open questions flagged.
59
100
 
60
101
  ### Changed
61
102
 
62
- - **Safety-first read-only repositioning.** README and `docs/product-plan.md §1` now lead with "read-only by architecture, not by configuration" as the primary identity. Pack candidate list updated: MCP 02 is now DdsForge (non-ROS DDS observability, zero-competition niche); DatasetForge slides to MCP 03. Strategic context in `docs/product-plan.md §4` and §8 (DDS-complete horizon).
103
+ - **Safety-first read-only repositioning.** README and `docs/product-plan.md §1` now lead with "read-only by architecture, not by configuration" as the primary identity. Pack candidate list updated: MCP 02 reframed to a non-ROS DDS observability MCP (later folded into TopicForge itself by the 2026-05-14 multi-vendor reframe — see v0.3.0 entry); DatasetForge slides to MCP 03. Strategic context in `docs/product-plan.md §4` and §8 (DDS-complete horizon).
63
104
  - **Internal API.** `Inspector.sample_messages` now returns a `SampleResult` envelope (previously a `list[MessageSample]`). The MCP-facing tool handler is reduced to a thin pass-through. No effect on the tool's wire-level response shape (handlers already wrapped the list into `SampleResult`), but flagged here for anyone importing `Inspector` directly outside this repo.
64
105
 
65
106
  ### Internal
@@ -105,7 +146,8 @@ Initial MVP release of TopicForge — ROS Topic Inspector & Bag Analyzer MCP ser
105
146
  - The write path (publishing, commanding robots) is intentionally out of scope for the MVP.
106
147
  - `analyze_bag` in live mode parses `ros2 bag info` text output; deeper anomaly detection remains mock-only for now.
107
148
 
108
- [Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.2.0...HEAD
149
+ [Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.3.0...HEAD
150
+ [0.3.0]: https://github.com/yaniswav/TopicForge/compare/v0.2.0...v0.3.0
109
151
  [0.2.0]: https://github.com/yaniswav/TopicForge/compare/v0.1.2...v0.2.0
110
152
  [0.1.2]: https://github.com/yaniswav/TopicForge/compare/v0.1.1...v0.1.2
111
153
  [0.1.1]: https://github.com/yaniswav/TopicForge/compare/v0.1.0...v0.1.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topicforge
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: ROS Topic Inspector & Bag Analyzer MCP server for AI agents
5
5
  Project-URL: Homepage, https://github.com/yaniswav/TopicForge
6
6
  Project-URL: Repository, https://github.com/yaniswav/TopicForge
@@ -42,8 +42,14 @@ Requires-Dist: mcp>=1.0.0
42
42
  Requires-Dist: pydantic>=2.6
43
43
  Provides-Extra: all
44
44
  Requires-Dist: cyclonedds>=0.10; extra == 'all'
45
+ Requires-Dist: fastdds<3,>=2.6.1; extra == 'all'
45
46
  Provides-Extra: dds
46
47
  Requires-Dist: cyclonedds>=0.10; extra == 'dds'
48
+ Requires-Dist: fastdds<3,>=2.6.1; extra == 'dds'
49
+ Provides-Extra: dds-cyclone
50
+ Requires-Dist: cyclonedds>=0.10; extra == 'dds-cyclone'
51
+ Provides-Extra: dds-fast
52
+ Requires-Dist: fastdds<3,>=2.6.1; extra == 'dds-fast'
47
53
  Provides-Extra: dev
48
54
  Requires-Dist: pytest>=8.0; extra == 'dev'
49
55
  Requires-Dist: ruff>=0.4; extra == 'dev'
@@ -56,7 +62,7 @@ Description-Content-Type: text/markdown
56
62
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/yaniswav/TopicForge/blob/main/LICENSE)
57
63
  [![Read-only by architecture](https://img.shields.io/badge/safety-read--only_by_architecture-2563eb)](https://github.com/yaniswav/TopicForge#security-model)
58
64
 
59
- > **The safety-first read-only MCP for ROS2 robotics — now with a DDS observability module (v0.2.0).** TopicForge lets AI agents inspect your ROS2 graph, ROS bag files, and (since v0.2.0) the raw DDS layer beneath ROS, without ever publishing back to the bus. The MCP client can see the stack ; it cannot touch it.
65
+ > **The safety-first read-only MCP for ROS2 robotics — now with multi-vendor OMG DDS-RTPS observability (v0.3.0).** TopicForge lets AI agents inspect your ROS2 graph, ROS bag files, and (since v0.2.0) the raw DDS layer beneath ROS, without ever publishing back to the bus. v0.3.0 ships two OSS Python adapters — Eclipse CycloneDDS and eProsima Fast DDS — each joining the bus as a read-only DDS-RTPS participant that observes **every conformant vendor on the wire** (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, etc.) via the OMG protocol guarantee. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md) for the canonical multi-vendor positioning and the OMG May 2025 interop reference.
60
66
 
61
67
  TopicForge is a production-minded MCP (Model Context Protocol) server that lets AI agents — such as Claude — inspect ROS2 topics, analyze ROS bag files, and (since v0.2.0) observe the raw DDS layer through a clean, structured tool interface. It is read-only by **architecture**, not by configuration: there is no write path to misconfigure, no permission system to audit, no liability conversation to have. The MCP client can see the robot stack; it cannot touch it.
62
68
 
@@ -188,15 +194,29 @@ TOPICFORGE_MODE=live python -m topicforge
188
194
 
189
195
  TopicForge invokes the `ros2` CLI under the hood, so it does **not** require `rclpy` to be importable. This keeps the live adapter portable across ROS2 distros.
190
196
 
191
- ### DDS support (v0.2.0+)
197
+ ### Multi-vendor DDS support (v0.3.0+)
192
198
 
193
- Beyond ROS2 graph introspection, TopicForge can also observe a raw DDS bus directly — useful for non-ROS DDS stacks (defense, aerospace, automotive AUTOSAR Adaptive, industrial integration) and for diagnosing why a ROS2 subscriber isn't receiving when the graph says it should. Same safety-first contract : read-only by **architecture**, never publishes back to the bus.
199
+ Beyond ROS2 graph introspection, TopicForge observes the raw DDS bus directly via one of two OSS Python adapters — Eclipse CycloneDDS or eProsima Fast DDS — each joining as a **read-only DDS-RTPS participant**. By the OMG-DDS-RTPS protocol guarantee, both adapters see every conformant participant on the domain (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, InterCOM, etc.) regardless of host language. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md) for the canonical multi-vendor positioning and the [OMG May 2025 interop reference](docs/projet-file/references/omg-dds-interop-2025-05-08.xlsx).
194
200
 
195
- Install the optional DDS extras and select a backend :
201
+ Useful for non-ROS DDS stacks (defense, aerospace, automotive AUTOSAR Adaptive, industrial integration) and for diagnosing why a ROS2 subscriber isn't receiving when the graph says it should. Same safety-first contract : read-only by **architecture** — the `MiddlewareAdapter` protocol does not expose a write method on any backend.
202
+
203
+ Install one or both OSS backends :
204
+
205
+ ```bash
206
+ # Single vendor — install only what you need
207
+ pip install topicforge[dds-cyclone] # Eclipse CycloneDDS only
208
+ pip install topicforge[dds-fast] # eProsima Fast DDS only
209
+ pip install topicforge[dds] # both OSS backends (union)
210
+ ```
211
+
212
+ Then select a backend :
196
213
 
197
214
  ```bash
198
- pip install topicforge[dds]
199
215
  TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
216
+ # or:
217
+ TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=fast python -m topicforge
218
+ # or, auto-select Fast > Cyclone > Mock:
219
+ TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=auto python -m topicforge
200
220
  ```
201
221
 
202
222
  Three new MCP tools (in addition to the five ROS2 tools above) :
@@ -207,11 +227,13 @@ Three new MCP tools (in addition to the five ROS2 tools above) :
207
227
  | `detect_qos_mismatches` | Reader/writer QoS incompatibilities preventing communication on a topic |
208
228
  | `peek_dds_samples` | Recent samples on a raw DDS topic (distinct from `sample_messages` on ROS2 graph)|
209
229
 
210
- **v0.2.0 limitation.** TopicForge selects one adapter at a time. With `TOPICFORGE_DDS_BACKEND=cyclone`, the 3 DDS tools work and the 5 ROS2 tools raise a clear `AdapterError` — and vice versa with the default `TOPICFORGE_DDS_BACKEND=mock`. The mock backend exposes all 8 tools against deterministic fixtures for local development and tests. Real CycloneDDS discovery (builtin topics, QoS pair extraction, typed reader for samples) ships as a v0.2.x patch ; the v0.2.0 `CycloneDdsAdapter` is a protocol-compliant stub that raises a clear roadmap message. A composite adapter delegating per-tool is a v0.2.x roadmap item.
230
+ **v0.3.0 limitation — single adapter at a time.** TopicForge selects one adapter per server run. With `TOPICFORGE_DDS_BACKEND=cyclone` (or `fast`), the 3 DDS tools work and the 5 ROS2 tools raise a clear `AdapterError` ; vice versa with the default `TOPICFORGE_DDS_BACKEND=mock`. The mock backend exposes all 8 tools against deterministic fixtures (incl. a `vendor="fast"` participant) for local development. A composite adapter delegating per-tool category is a v0.3.x roadmap item.
231
+
232
+ **v0.3.0 limitation — `peek_dds_samples` scope.** Full-fidelity on the 4 builtin DCPS topics (`DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`) ; arbitrary user topics raise an `AdapterError` pointing at the v0.3.x XTypes/IDL roadmap. The other two DDS tools (`list_participants`, `detect_qos_mismatches`) work end-to-end on any user-topic deployment.
211
233
 
212
- `RTI Connext` and additional vendors will be available in the Pro tier (see `docs/pro.md`).
234
+ **`RTI Connext`** is v0.4.0+ Pro tier (BYO license — see `docs/pro.md`).
213
235
 
214
- **Full 5-minute walkthrough** — including the canonical QoS-mismatch debugging scenario, the single-adapter limitation matrix, and troubleshooting — lives in [`docs/DDS_QUICKSTART.md`](docs/DDS_QUICKSTART.md).
236
+ **Full 5-minute walkthrough** — backend selection, the canonical QoS-mismatch debugging scenario, troubleshooting — lives in [`docs/DDS_QUICKSTART.md`](docs/DDS_QUICKSTART.md). Migration from v0.2.0 in [`docs/MIGRATION_v0.2_to_v0.3.md`](docs/MIGRATION_v0.2_to_v0.3.md).
215
237
 
216
238
  ### Configure with Claude Desktop
217
239
 
@@ -266,7 +288,7 @@ make check # both, plus tests (CI bundle)
266
288
  | `TOPICFORGE_LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
267
289
  | `TOPICFORGE_ROS2_BIN` | `ros2` | Name (or path) of the ROS2 CLI binary |
268
290
  | `TOPICFORGE_TELEMETRY` | `off` | Opt-in anonymous usage telemetry. See [Telemetry](#telemetry). |
269
- | `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `rti`, or `auto`. See [DDS support](#dds-support-v020). |
291
+ | `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `fast`, `rti`, or `auto`. `auto` resolves to Fast > Cyclone > Mock. See [Multi-vendor DDS support](#multi-vendor-dds-support-v030). |
270
292
  | `TOPICFORGE_DDS_DOMAIN_ID` | `0` | DDS domain id observed (0..232) when a DDS backend is active. |
271
293
 
272
294
  See [`.env.example`](.env.example).
@@ -341,7 +363,10 @@ See [`docs/product-plan.md`](docs/product-plan.md) for the full product trajecto
341
363
  Near-term additions on the bench:
342
364
 
343
365
  - `rclpy`-backed live adapter for faster & richer sampling
344
- - DDS observability module (Cyclone DDS first as an `extras` install — `pip install topicforge[dds]` —, RTI Connext later in the Pro tier). Generalizes the existing `RosAdapter` to a `MiddlewareAdapter` protocol. Same safety-first read-only contract.
366
+ - XTypes/IDL discovery to extend `peek_dds_samples` to arbitrary user topics (today: 4 builtin DCPS topics only) — v0.3.x patch
367
+ - Extended QoS coverage (Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget) — v0.3.x patch
368
+ - Composite adapter delegating per-tool category, so ROS2 + DDS surfaces work simultaneously — v0.3.x patch
369
+ - `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`) — v0.4.0+
345
370
  - URDF inspector / validator MCP tools
346
371
  - Bag anomaly detection (clock jumps, gaps, dropped frames, TF tree health)
347
372
  - Dataset export helpers (rosbag → COCO / HF Datasets)
@@ -365,10 +390,13 @@ topicforge-mcp/
365
390
  │ ├── services/ # Domain orchestration
366
391
  │ ├── adapters/
367
392
  │ │ ├── ros2_live/ # `ros2` CLI wrappers
368
- │ │ └── ros2_mock/ # Deterministic fixtures
393
+ │ │ ├── ros2_mock/ # Deterministic fixtures (incl. DDS)
394
+ │ │ ├── dds_cyclone/ # Eclipse CycloneDDS adapter (lazy import)
395
+ │ │ ├── dds_fast/ # eProsima Fast DDS adapter (lazy import)
396
+ │ │ └── common/ # Vendor-neutral helpers + pure QoS analyzer
369
397
  │ ├── models/ # Pydantic schemas
370
398
  │ └── config/ # Settings & mode resolution
371
- └── tests/ # Pytest suite (mock-only, no ROS2 required)
399
+ └── tests/ # Pytest suite (mock-only, no ROS2/DDS required)
372
400
  ```
373
401
 
374
402
  ## License
@@ -5,7 +5,7 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/yaniswav/TopicForge/blob/main/LICENSE)
6
6
  [![Read-only by architecture](https://img.shields.io/badge/safety-read--only_by_architecture-2563eb)](https://github.com/yaniswav/TopicForge#security-model)
7
7
 
8
- > **The safety-first read-only MCP for ROS2 robotics — now with a DDS observability module (v0.2.0).** TopicForge lets AI agents inspect your ROS2 graph, ROS bag files, and (since v0.2.0) the raw DDS layer beneath ROS, without ever publishing back to the bus. The MCP client can see the stack ; it cannot touch it.
8
+ > **The safety-first read-only MCP for ROS2 robotics — now with multi-vendor OMG DDS-RTPS observability (v0.3.0).** TopicForge lets AI agents inspect your ROS2 graph, ROS bag files, and (since v0.2.0) the raw DDS layer beneath ROS, without ever publishing back to the bus. v0.3.0 ships two OSS Python adapters — Eclipse CycloneDDS and eProsima Fast DDS — each joining the bus as a read-only DDS-RTPS participant that observes **every conformant vendor on the wire** (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, etc.) via the OMG protocol guarantee. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md) for the canonical multi-vendor positioning and the OMG May 2025 interop reference.
9
9
 
10
10
  TopicForge is a production-minded MCP (Model Context Protocol) server that lets AI agents — such as Claude — inspect ROS2 topics, analyze ROS bag files, and (since v0.2.0) observe the raw DDS layer through a clean, structured tool interface. It is read-only by **architecture**, not by configuration: there is no write path to misconfigure, no permission system to audit, no liability conversation to have. The MCP client can see the robot stack; it cannot touch it.
11
11
 
@@ -137,15 +137,29 @@ TOPICFORGE_MODE=live python -m topicforge
137
137
 
138
138
  TopicForge invokes the `ros2` CLI under the hood, so it does **not** require `rclpy` to be importable. This keeps the live adapter portable across ROS2 distros.
139
139
 
140
- ### DDS support (v0.2.0+)
140
+ ### Multi-vendor DDS support (v0.3.0+)
141
141
 
142
- Beyond ROS2 graph introspection, TopicForge can also observe a raw DDS bus directly — useful for non-ROS DDS stacks (defense, aerospace, automotive AUTOSAR Adaptive, industrial integration) and for diagnosing why a ROS2 subscriber isn't receiving when the graph says it should. Same safety-first contract : read-only by **architecture**, never publishes back to the bus.
142
+ Beyond ROS2 graph introspection, TopicForge observes the raw DDS bus directly via one of two OSS Python adapters — Eclipse CycloneDDS or eProsima Fast DDS — each joining as a **read-only DDS-RTPS participant**. By the OMG-DDS-RTPS protocol guarantee, both adapters see every conformant participant on the domain (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, InterCOM, etc.) regardless of host language. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md) for the canonical multi-vendor positioning and the [OMG May 2025 interop reference](docs/projet-file/references/omg-dds-interop-2025-05-08.xlsx).
143
143
 
144
- Install the optional DDS extras and select a backend :
144
+ Useful for non-ROS DDS stacks (defense, aerospace, automotive AUTOSAR Adaptive, industrial integration) and for diagnosing why a ROS2 subscriber isn't receiving when the graph says it should. Same safety-first contract : read-only by **architecture** — the `MiddlewareAdapter` protocol does not expose a write method on any backend.
145
+
146
+ Install one or both OSS backends :
147
+
148
+ ```bash
149
+ # Single vendor — install only what you need
150
+ pip install topicforge[dds-cyclone] # Eclipse CycloneDDS only
151
+ pip install topicforge[dds-fast] # eProsima Fast DDS only
152
+ pip install topicforge[dds] # both OSS backends (union)
153
+ ```
154
+
155
+ Then select a backend :
145
156
 
146
157
  ```bash
147
- pip install topicforge[dds]
148
158
  TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
159
+ # or:
160
+ TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=fast python -m topicforge
161
+ # or, auto-select Fast > Cyclone > Mock:
162
+ TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=auto python -m topicforge
149
163
  ```
150
164
 
151
165
  Three new MCP tools (in addition to the five ROS2 tools above) :
@@ -156,11 +170,13 @@ Three new MCP tools (in addition to the five ROS2 tools above) :
156
170
  | `detect_qos_mismatches` | Reader/writer QoS incompatibilities preventing communication on a topic |
157
171
  | `peek_dds_samples` | Recent samples on a raw DDS topic (distinct from `sample_messages` on ROS2 graph)|
158
172
 
159
- **v0.2.0 limitation.** TopicForge selects one adapter at a time. With `TOPICFORGE_DDS_BACKEND=cyclone`, the 3 DDS tools work and the 5 ROS2 tools raise a clear `AdapterError` — and vice versa with the default `TOPICFORGE_DDS_BACKEND=mock`. The mock backend exposes all 8 tools against deterministic fixtures for local development and tests. Real CycloneDDS discovery (builtin topics, QoS pair extraction, typed reader for samples) ships as a v0.2.x patch ; the v0.2.0 `CycloneDdsAdapter` is a protocol-compliant stub that raises a clear roadmap message. A composite adapter delegating per-tool is a v0.2.x roadmap item.
173
+ **v0.3.0 limitation — single adapter at a time.** TopicForge selects one adapter per server run. With `TOPICFORGE_DDS_BACKEND=cyclone` (or `fast`), the 3 DDS tools work and the 5 ROS2 tools raise a clear `AdapterError` ; vice versa with the default `TOPICFORGE_DDS_BACKEND=mock`. The mock backend exposes all 8 tools against deterministic fixtures (incl. a `vendor="fast"` participant) for local development. A composite adapter delegating per-tool category is a v0.3.x roadmap item.
174
+
175
+ **v0.3.0 limitation — `peek_dds_samples` scope.** Full-fidelity on the 4 builtin DCPS topics (`DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`) ; arbitrary user topics raise an `AdapterError` pointing at the v0.3.x XTypes/IDL roadmap. The other two DDS tools (`list_participants`, `detect_qos_mismatches`) work end-to-end on any user-topic deployment.
160
176
 
161
- `RTI Connext` and additional vendors will be available in the Pro tier (see `docs/pro.md`).
177
+ **`RTI Connext`** is v0.4.0+ Pro tier (BYO license — see `docs/pro.md`).
162
178
 
163
- **Full 5-minute walkthrough** — including the canonical QoS-mismatch debugging scenario, the single-adapter limitation matrix, and troubleshooting — lives in [`docs/DDS_QUICKSTART.md`](docs/DDS_QUICKSTART.md).
179
+ **Full 5-minute walkthrough** — backend selection, the canonical QoS-mismatch debugging scenario, troubleshooting — lives in [`docs/DDS_QUICKSTART.md`](docs/DDS_QUICKSTART.md). Migration from v0.2.0 in [`docs/MIGRATION_v0.2_to_v0.3.md`](docs/MIGRATION_v0.2_to_v0.3.md).
164
180
 
165
181
  ### Configure with Claude Desktop
166
182
 
@@ -215,7 +231,7 @@ make check # both, plus tests (CI bundle)
215
231
  | `TOPICFORGE_LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
216
232
  | `TOPICFORGE_ROS2_BIN` | `ros2` | Name (or path) of the ROS2 CLI binary |
217
233
  | `TOPICFORGE_TELEMETRY` | `off` | Opt-in anonymous usage telemetry. See [Telemetry](#telemetry). |
218
- | `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `rti`, or `auto`. See [DDS support](#dds-support-v020). |
234
+ | `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `fast`, `rti`, or `auto`. `auto` resolves to Fast > Cyclone > Mock. See [Multi-vendor DDS support](#multi-vendor-dds-support-v030). |
219
235
  | `TOPICFORGE_DDS_DOMAIN_ID` | `0` | DDS domain id observed (0..232) when a DDS backend is active. |
220
236
 
221
237
  See [`.env.example`](.env.example).
@@ -290,7 +306,10 @@ See [`docs/product-plan.md`](docs/product-plan.md) for the full product trajecto
290
306
  Near-term additions on the bench:
291
307
 
292
308
  - `rclpy`-backed live adapter for faster & richer sampling
293
- - DDS observability module (Cyclone DDS first as an `extras` install — `pip install topicforge[dds]` —, RTI Connext later in the Pro tier). Generalizes the existing `RosAdapter` to a `MiddlewareAdapter` protocol. Same safety-first read-only contract.
309
+ - XTypes/IDL discovery to extend `peek_dds_samples` to arbitrary user topics (today: 4 builtin DCPS topics only) — v0.3.x patch
310
+ - Extended QoS coverage (Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget) — v0.3.x patch
311
+ - Composite adapter delegating per-tool category, so ROS2 + DDS surfaces work simultaneously — v0.3.x patch
312
+ - `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`) — v0.4.0+
294
313
  - URDF inspector / validator MCP tools
295
314
  - Bag anomaly detection (clock jumps, gaps, dropped frames, TF tree health)
296
315
  - Dataset export helpers (rosbag → COCO / HF Datasets)
@@ -314,10 +333,13 @@ topicforge-mcp/
314
333
  │ ├── services/ # Domain orchestration
315
334
  │ ├── adapters/
316
335
  │ │ ├── ros2_live/ # `ros2` CLI wrappers
317
- │ │ └── ros2_mock/ # Deterministic fixtures
336
+ │ │ ├── ros2_mock/ # Deterministic fixtures (incl. DDS)
337
+ │ │ ├── dds_cyclone/ # Eclipse CycloneDDS adapter (lazy import)
338
+ │ │ ├── dds_fast/ # eProsima Fast DDS adapter (lazy import)
339
+ │ │ └── common/ # Vendor-neutral helpers + pure QoS analyzer
318
340
  │ ├── models/ # Pydantic schemas
319
341
  │ └── config/ # Settings & mode resolution
320
- └── tests/ # Pytest suite (mock-only, no ROS2 required)
342
+ └── tests/ # Pytest suite (mock-only, no ROS2/DDS required)
321
343
  ```
322
344
 
323
345
  ## License
@@ -0,0 +1,156 @@
1
+ # DDS quickstart — TopicForge v0.3.0+
2
+
3
+ A 5-minute tour of TopicForge's multi-vendor DDS observability module. Both backends — Eclipse CycloneDDS and eProsima Fast DDS — join the bus as **read-only DDS-RTPS participants** and observe every conformant vendor on the wire via the OMG protocol guarantee. The `MiddlewareAdapter` protocol does not expose a write method, so the MCP client cannot publish back to the bus on any backend.
4
+
5
+ See [`docs/dds-interop-matrix.md`](dds-interop-matrix.md) for the canonical multi-vendor positioning and the [OMG May 2025 interop reference](projet-file/references/omg-dds-interop-2025-05-08.xlsx).
6
+
7
+ This guide does **not** assume you have ROS2 installed.
8
+
9
+ ---
10
+
11
+ ## 1. Mock mode — 30-second demo
12
+
13
+ The deterministic mock fixtures expose the full DDS tool surface without any DDS SDK or middleware. Useful for evaluating the tools before pulling in a real broker.
14
+
15
+ ```bash
16
+ pip install topicforge
17
+ TOPICFORGE_MODE=mock python -m topicforge
18
+ ```
19
+
20
+ In the spawned MCP client (Claude Desktop, Claude Code, Cursor, ...), the 3 DDS tools are now available alongside the 5 ROS2 tools:
21
+
22
+ - `list_participants(domain_id=0)` → returns 3 mock participants on domain 0 — two CycloneDDS (`mock-robot`, `mock-laptop`) and one Fast DDS (`mock-aerospace-node`). The multi-vendor mock exercises the canonical vendor enum (`cyclone`, `fast`, `rti`, `mock`, `unknown`).
23
+ - `detect_qos_mismatches(topic=None)` → returns 1 `MismatchReport` for `/dds/qos_mismatch` (deliberate Reliability incompatibility — RELIABLE reader vs BEST_EFFORT writer).
24
+ - `peek_dds_samples(topic="/dds/well_matched", count=3)` → returns 3 deterministic samples ; `peek_dds_samples(topic="/dds/qos_mismatch", count=1)` returns 1 sample with a `qos_note` field annotating the mismatch.
25
+
26
+ Mock fixtures are stable across runs — you can write integration tests against them.
27
+
28
+ ---
29
+
30
+ ## 2. Live mode — choose your backend
31
+
32
+ v0.3.0 ships two OSS Python adapters. Pick one (or install both) :
33
+
34
+ ### 2.a Eclipse CycloneDDS
35
+
36
+ ```bash
37
+ pip install topicforge[dds-cyclone]
38
+ TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
39
+ ```
40
+
41
+ The CycloneDDS adapter uses `cyclonedds.builtin.BuiltinDataReader` for polling-style discovery on the DCPS builtin topics. QoS policies are introspected via `Policy.*` class names. Bounded `take_iter` timeouts keep tool calls under 2 seconds.
42
+
43
+ ### 2.b eProsima Fast DDS
44
+
45
+ ```bash
46
+ pip install topicforge[dds-fast]
47
+ TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=fast python -m topicforge
48
+ ```
49
+
50
+ The Fast DDS adapter attaches a `DomainParticipantListener`-shaped object to a freshly created participant and accumulates discovery callbacks under an RLock. A bounded `discovery_wait_ms=1500` warm-up after participant creation gives the listener time to populate before the first tool call.
51
+
52
+ ### 2.c Both backends + auto resolution
53
+
54
+ ```bash
55
+ pip install topicforge[dds] # both Cyclone and Fast
56
+ TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=auto python -m topicforge
57
+ ```
58
+
59
+ `auto` resolves to the first available OSS backend in this order: `fast` > `cyclone` > `mock`. The order reflects the OMG May 2025 interop matrix where Fast DDS is validated against all five other vendors on 47/47 pairs. v0.2.0 users with only `cyclonedds` installed remain unchanged — Fast is unimportable on their host so the chain falls through to Cyclone.
60
+
61
+ ### Domain selection
62
+
63
+ ```bash
64
+ TOPICFORGE_DDS_DOMAIN_ID=42 python -m topicforge
65
+ ```
66
+
67
+ Accepts `0..232` (DDS spec range). Default is `0` — the same default used by most ROS2 setups.
68
+
69
+ ### Pro tier — RTI Connext
70
+
71
+ `TOPICFORGE_DDS_BACKEND=rti` is reserved for the v0.4.0+ Pro tier (BYO RTI Connext license). Selecting it in the OSS core falls back to the ROS2 CLI adapter with a logged warning.
72
+
73
+ ---
74
+
75
+ ## 3. The QoS mismatch scenario
76
+
77
+ Both real backends and the mock fixtures encode the canonical "subscriber doesn't receive" debugging case. From an MCP client:
78
+
79
+ ```
80
+ > Detect QoS mismatches on the current bus.
81
+
82
+ [tool call: detect_qos_mismatches]
83
+ [result]
84
+ [
85
+ {
86
+ "topic": "/dds/qos_mismatch",
87
+ "reader_guid": "010f1c2a.3b4c5d6e.7f800000.00000001",
88
+ "writer_guid": "010f1c2a.3b4c5d6e.7f800000.00000002",
89
+ "incompatible_policies": ["Reliability"],
90
+ "severity": "incompatible",
91
+ "mode_effective": "mock"
92
+ }
93
+ ]
94
+ ```
95
+
96
+ An LLM reading this output has enough information to suggest a concrete fix ("the writer is BEST_EFFORT but the reader requires RELIABLE — either relax the reader or upgrade the writer"). That is the diagnostic loop the DDS module is designed to support — and it works identically regardless of which backend produced the discovery samples, because the vendor-neutral pure analyzer at `src/topicforge/adapters/common/qos_analyzer.py` operates on canonical `QosProfile` Pydantic models.
97
+
98
+ The analyzer covers the four MVP policies — **Reliability**, **Durability**, **History**, **Deadline** — that explain the bulk of real-world mismatch cases. Liveliness, Ownership, Partition, TimeBasedFilter, and LatencyBudget are v0.3.x patches.
99
+
100
+ ---
101
+
102
+ ## 4. Single-adapter limitation (v0.3.0)
103
+
104
+ TopicForge v0.3.0 still selects **one adapter at a time** based on `TOPICFORGE_MODE` + `TOPICFORGE_DDS_BACKEND` :
105
+
106
+ | `TOPICFORGE_MODE` | `TOPICFORGE_DDS_BACKEND` | Active adapter | ROS2 tools | DDS tools |
107
+ | ----------------- | ------------------------ | -------------------------- | ------------------------- | -------------------------- |
108
+ | `mock` | (any) | `MockAdapter` | work (fixtures) | work (fixtures) |
109
+ | `live` / `auto` | `mock` (default) | `Ros2CliAdapter` | work | raise with remediation |
110
+ | `live` / `auto` | `cyclone` | `CycloneDdsAdapter` | raise (DDS-only adapter) | work (real CycloneDDS) |
111
+ | `live` / `auto` | `fast` | `FastDdsAdapter` | raise (DDS-only adapter) | work (real Fast DDS) |
112
+ | `live` / `auto` | `rti` | falls back to ROS2 CLI | work (CLI) | raise (v0.4.0+ Pro tier) |
113
+
114
+ A composite adapter that delegates per-tool category (ROS2 graph vs DDS layer) is on the v0.3.x roadmap. For now, restart the server with a different `TOPICFORGE_DDS_BACKEND` to switch sides.
115
+
116
+ Error messages on the unselected side are explicit and point at the remediation path — no silent failures.
117
+
118
+ ---
119
+
120
+ ## 5. v0.3.0 scope of `peek_dds_samples`
121
+
122
+ `peek_dds_samples` is full-fidelity on the 4 builtin DCPS topics with both backends :
123
+
124
+ ```
125
+ peek_dds_samples(topic="DCPSParticipant", count=5)
126
+ peek_dds_samples(topic="DCPSSubscription", count=10)
127
+ peek_dds_samples(topic="DCPSPublication", count=10)
128
+ ```
129
+
130
+ Arbitrary user topics raise an `AdapterError` pointing at the v0.3.x roadmap — XTypes/IDL discovery (`cyclonedds.dynamic.get_types_for_typeid` on Cyclone, XTypes remote-type lookup on Fast DDS) is the missing piece for arbitrary user-topic peek.
131
+
132
+ The other two DDS tools — `list_participants` and `detect_qos_mismatches` — work end-to-end on any user-topic deployment ; they don't depend on payload deserialization.
133
+
134
+ ---
135
+
136
+ ## 6. What's next
137
+
138
+ - **v0.3.x patch** — XTypes/IDL discovery to extend `peek_dds_samples` to arbitrary user topics on both backends.
139
+ - **v0.3.x patch** — Extended QoS coverage : Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget.
140
+ - **v0.3.x patch** — Composite adapter routing ROS2 graph tools to `Ros2CliAdapter` and DDS tools to the selected DDS adapter, so both surfaces are usable simultaneously.
141
+ - **v0.4.0+** — `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`).
142
+
143
+ Full strategic roadmap lives in [`docs/product-plan.md`](product-plan.md) and the DDS module spec at [`docs/projet-file/mcp-02-spec.md`](projet-file/mcp-02-spec.md).
144
+
145
+ ---
146
+
147
+ ## 7. Troubleshooting
148
+
149
+ - **`pip install topicforge[dds-cyclone]` fails on Windows / macOS Python 3.13+** — `cyclonedds` wheels are typically published for Python 3.8 to 3.12. Pin Python 3.11 or 3.12 for the install host.
150
+ - **`pip install topicforge[dds-cyclone]` fails with `CYCLONEDDS_HOME`** — pip is trying to build `cyclonedds` from source because no wheel matches your platform/Python combination. Either switch to a supported Python (3.11/3.12) or install the native CycloneDDS C library first (see Eclipse CycloneDDS releases).
151
+ - **`pip install topicforge[dds-fast]` fails** — eProsima Fast DDS Python bindings (`fastdds>=2.6.1,<3`) currently ship wheels for Linux first. Windows wheels lag ; consult fast-dds.docs.eprosima.com for the current matrix.
152
+ - **DDS tool returns "v0.3.x roadmap" error** — you called `peek_dds_samples` on an arbitrary user topic. The 4 builtin DCPS topics work today ; arbitrary user-topic peek is a v0.3.x patch (XTypes/IDL discovery).
153
+ - **DDS tool returns "DDS module is not active" error** — your `TOPICFORGE_DDS_BACKEND` is `mock` while `TOPICFORGE_MODE` is `live` (the ROS2 CLI adapter is selected). Set `TOPICFORGE_DDS_BACKEND=cyclone` or `=fast` explicitly to enable the DDS adapters.
154
+ - **`auto` selects the wrong backend** — `auto` prefers Fast > Cyclone > Mock. If you want Cyclone explicitly, set `TOPICFORGE_DDS_BACKEND=cyclone` rather than relying on `auto`.
155
+
156
+ Report issues at https://github.com/yaniswav/TopicForge/issues.