topicforge 0.4.0__tar.gz → 0.5.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 (99) hide show
  1. {topicforge-0.4.0 → topicforge-0.5.0}/.gitignore +6 -0
  2. {topicforge-0.4.0 → topicforge-0.5.0}/CHANGELOG.md +163 -2
  3. {topicforge-0.4.0 → topicforge-0.5.0}/PKG-INFO +24 -21
  4. {topicforge-0.4.0 → topicforge-0.5.0}/README.md +22 -20
  5. {topicforge-0.4.0 → topicforge-0.5.0}/docs/DDS_QUICKSTART.md +30 -21
  6. topicforge-0.5.0/docs/MIGRATION_v0.3_to_v0.4.md +242 -0
  7. {topicforge-0.4.0 → topicforge-0.5.0}/docs/TESTING.md +12 -3
  8. topicforge-0.5.0/docs/TROUBLESHOOTING.md +245 -0
  9. topicforge-0.5.0/examples/README.md +30 -0
  10. {topicforge-0.4.0 → topicforge-0.5.0}/pyproject.toml +2 -1
  11. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/__init__.py +1 -1
  12. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/common/dds_helpers.py +15 -5
  13. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/dds_cyclone/adapter.py +13 -3
  14. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/dds_fast/adapter.py +9 -2
  15. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/services/bag_service.py +10 -3
  16. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/services/inspector.py +6 -5
  17. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_bag_service.py +41 -0
  18. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_dds_helpers.py +22 -0
  19. {topicforge-0.4.0 → topicforge-0.5.0}/LICENSE +0 -0
  20. {topicforge-0.4.0 → topicforge-0.5.0}/docs/MIGRATION_v0.1_to_v0.2.md +0 -0
  21. {topicforge-0.4.0 → topicforge-0.5.0}/docs/MIGRATION_v0.2_to_v0.3.md +0 -0
  22. {topicforge-0.4.0 → topicforge-0.5.0}/docs/dds-interop-matrix.md +0 -0
  23. {topicforge-0.4.0 → topicforge-0.5.0}/docs/pro.md +0 -0
  24. {topicforge-0.4.0 → topicforge-0.5.0}/docs/product-plan.md +0 -0
  25. {topicforge-0.4.0 → topicforge-0.5.0}/scripts/integration/README.md +0 -0
  26. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/__main__.py +0 -0
  27. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/__init__.py +0 -0
  28. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/base.py +0 -0
  29. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/common/__init__.py +0 -0
  30. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/common/cdr_decoder.py +0 -0
  31. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/common/lifecycle.py +0 -0
  32. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/common/metrics_buffer.py +0 -0
  33. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/common/qos_analyzer.py +0 -0
  34. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/common/xtypes.py +0 -0
  35. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/composite.py +0 -0
  36. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/dds_cyclone/__init__.py +0 -0
  37. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/dds_dust/__init__.py +0 -0
  38. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/dds_dust/adapter.py +0 -0
  39. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/dds_fast/__init__.py +0 -0
  40. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/dds_opendds/__init__.py +0 -0
  41. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/dds_opendds/adapter.py +0 -0
  42. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/ros2_live/__init__.py +0 -0
  43. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/ros2_live/adapter.py +0 -0
  44. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/ros2_mock/__init__.py +0 -0
  45. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/ros2_mock/adapter.py +0 -0
  46. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/adapters/ros2_mock/fixtures.py +0 -0
  47. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/config/__init__.py +0 -0
  48. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/config/settings.py +0 -0
  49. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/models/__init__.py +0 -0
  50. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/models/schemas.py +0 -0
  51. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/server/__init__.py +0 -0
  52. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/server/app.py +0 -0
  53. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/services/__init__.py +0 -0
  54. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/services/constants.py +0 -0
  55. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/services/factory.py +0 -0
  56. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/services/health.py +0 -0
  57. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/telemetry/__init__.py +0 -0
  58. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/telemetry/client.py +0 -0
  59. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/tools/__init__.py +0 -0
  60. {topicforge-0.4.0 → topicforge-0.5.0}/src/topicforge/tools/handlers.py +0 -0
  61. {topicforge-0.4.0 → topicforge-0.5.0}/tests/__init__.py +0 -0
  62. {topicforge-0.4.0 → topicforge-0.5.0}/tests/conftest.py +0 -0
  63. {topicforge-0.4.0 → topicforge-0.5.0}/tests/fixtures/csv_echo_imu.txt +0 -0
  64. {topicforge-0.4.0 → topicforge-0.5.0}/tests/fixtures/csv_echo_pose_multi.txt +0 -0
  65. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/__init__.py +0 -0
  66. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/conftest.py +0 -0
  67. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/scenarios/lifecycle_tracking.json +0 -0
  68. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/scenarios/multi_vendor_basic.json +0 -0
  69. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/scenarios/qos_mismatch_detection.json +0 -0
  70. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/scenarios/topic_metrics_frequency.json +0 -0
  71. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/scenarios/topic_metrics_sequence_gaps.json +0 -0
  72. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/scenarios/xtypes_decode.json +0 -0
  73. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/test_real_bus.py +0 -0
  74. {topicforge-0.4.0 → topicforge-0.5.0}/tests/integration/test_scenarios_schema.py +0 -0
  75. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_analyze_bag_multi_format.py +0 -0
  76. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_cdr_decoder.py +0 -0
  77. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_composite_adapter.py +0 -0
  78. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_config.py +0 -0
  79. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_cyclone_adapter.py +0 -0
  80. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_dds_cross_vendor.py +0 -0
  81. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_dds_schemas.py +0 -0
  82. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_dust_adapter.py +0 -0
  83. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_factory.py +0 -0
  84. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_fast_adapter.py +0 -0
  85. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_health.py +0 -0
  86. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_inspector.py +0 -0
  87. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_lifecycle_buffer.py +0 -0
  88. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_live_adapter_parse.py +0 -0
  89. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_live_adapter_subprocess.py +0 -0
  90. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_metrics_buffer.py +0 -0
  91. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_mock_adapter.py +0 -0
  92. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_opendds_adapter.py +0 -0
  93. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_peek_bag_samples.py +0 -0
  94. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_pro_hook.py +0 -0
  95. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_qos_analyzer.py +0 -0
  96. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_telemetry.py +0 -0
  97. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_tools_integration.py +0 -0
  98. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_topic_metrics.py +0 -0
  99. {topicforge-0.4.0 → topicforge-0.5.0}/tests/test_xtypes.py +0 -0
@@ -217,6 +217,12 @@ CLAUDE*.md
217
217
  # remain reproducible. Tracked, not part of sdist.
218
218
  !/docs/projet-file/references/
219
219
  !/docs/projet-file/references/**
220
+ # Archive of superseded strategic artifacts (old audit reports, dated
221
+ # launch-post drafts). Kept in git so the historical context survives
222
+ # but tucked away so the active `projet-file/` folder stays focused on
223
+ # what is currently load-bearing.
224
+ !/docs/projet-file/archive/
225
+ !/docs/projet-file/archive/**
220
226
  /docs/assets/screencast-raw/
221
227
 
222
228
 
@@ -5,7 +5,166 @@ All notable changes to TopicForge are documented in this file.
5
5
  The format is based on [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.4.0]
8
+ ## [Unreleased]
9
+
10
+ ## [0.5.0] - 2026-05-21
11
+
12
+ ### Sprint v0.5.0 — Polish + validation (pre-marketing-publication)
13
+
14
+ > Branch `feat/v0.5.0-polish-and-validation`. Three sub-milestones
15
+ > (5.1 real validation, 5.2 audit closure + error polish, 5.3 docs +
16
+ > examples + repo polish). No new MCP tool, no schema change. Last
17
+ > sprint before marketing publication ; the next version bump is
18
+ > the maintainer's manual `release` commit + tag.
19
+
20
+ #### Changed (sub-milestone 5.1 — Real validation)
21
+
22
+ - **CI matrix expanded** (`.github/workflows/ci.yml`) from
23
+ `ubuntu-latest × {3.11, 3.12}` to `{ubuntu-latest, windows-latest} ×
24
+ {3.11, 3.12, 3.13}` (6 cells, `fail-fast: false`). Windows-latest
25
+ coverage closes the largest unverified surface — TopicForge's primary
26
+ dev environment is Windows per `CLAUDE.md §7` and was previously only
27
+ hand-validated. Python 3.13 added now that wheels are stable across
28
+ the dependency footprint.
29
+ - **`pyproject.toml` classifiers** widened with `Programming Language ::
30
+ Python :: 3.13`.
31
+
32
+ #### Changed (sub-milestone 5.2 — AdapterError polish)
33
+
34
+ - **`DDS_ONLY_ERROR_MSG`** (`adapters/common/dds_helpers.py`) rewritten
35
+ with the v0.4.0 `CompositeAdapter` remediation path explicit, and
36
+ with every affected ROS2 tool name listed inline. Substring
37
+ `"DDS observability only"`, `"TOPICFORGE_DDS_BACKEND"`,
38
+ `"TOPICFORGE_MODE"` preserved — existing `pytest.raises(match=...)`
39
+ contracts honored. New token assertions added :
40
+ `"CompositeAdapter"`, the 4 affected tool names.
41
+ - **CycloneDDS adapter errors** (`adapters/dds_cyclone/adapter.py`)
42
+ enriched with the underlying exception type, the active domain id,
43
+ the topic name (where relevant), and common-cause diagnostic hints
44
+ (`CYCLONEDDS_URI` misconfiguration, multicast firewall, domain
45
+ mismatch). Three sites : participant discovery, endpoint discovery,
46
+ sample peek.
47
+ - **Fast DDS participant-init error** (`adapters/dds_fast/adapter.py`)
48
+ enriched with an ABI-mismatch diagnostic — Fast DDS 2.6.x Python
49
+ binding wheels frequently desynchronize with system-installed Fast
50
+ DDS native libraries, and the v0.4.0 wording masked the cause behind
51
+ a bare `"returned None"`. New message points at the pyproject pin
52
+ (`fastdds>=2.6.1,<3`) and the `FastDDS_DEFAULT_PROFILES_FILE` env
53
+ var as the two likely culprits.
54
+ - **`BagService` IO errors** (`services/bag_service.py`) wrap the
55
+ rosbags-side exception class name into the AdapterError message so
56
+ the LLM caller can pivot on `PermissionError` / `IsADirectoryError`
57
+ / etc. without inspecting `__cause__`.
58
+ - **`_ROSBAGS_REQUIRED_MSG`** rewording — clarifies that `analyze_bag`
59
+ has a v0.3.0 text-parse fallback while `peek_bag_samples` does not.
60
+
61
+ #### Closed (sub-milestone 5.2 — audit triage)
62
+
63
+ - **`docs/projet-file/audit-followup-triage-v0.2.0.md` refreshed**
64
+ against the current tree (was last touched pre-v0.3.0). Strict
65
+ B-class : 3 items now CLOSED (B6 in v0.2.0, B9 in v0.3.0, B10 in
66
+ v0.5.0). 6 items remain DEFER (B1-B5 hosted-context security
67
+ hardening ; B7, B8 wire-contract decisions for v0.6+).
68
+ - **`TODO(roadmap, audit-2026-05-14)` at `services/inspector.py:76`
69
+ retired as WONT-FIX-by-design** — the `list_topics` Inspector gate
70
+ is intentionally empty (no MCP-level args to validate). The comment
71
+ block is now a permanent design note rather than a roadmap pointer.
72
+
73
+ #### Added (sub-milestone 5.2 — regression tests)
74
+
75
+ - **5 new tests** in `tests/test_dds_helpers.py` and
76
+ `tests/test_bag_service.py` (regex-token assertions, not exact
77
+ wording) — pin the polished message contract without locking the
78
+ exact prose. Baseline grows from 394 to 399 passed ; 24 skipped
79
+ unchanged ; ruff clean.
80
+
81
+ #### Changed (sub-milestone 5.3 — Documentation cascade)
82
+
83
+ - **`README.md`** — CI badge added ; tagline refreshed from "v0.3.0"
84
+ to "v0.4.0" framing emphasising observability + bag analysis ; the
85
+ 3-row DDS tool mini-table grew into a 6-row table listing every
86
+ DDS / observability tool with its sub-milestone of origin ;
87
+ `peek_dds_samples` scope rewritten around `_decode_status` (full /
88
+ partial / raw) ; telemetry contract field description switched from
89
+ "five MVP tools" to "eleven MCP tools" ; `TOPICFORGE_DDS_BACKEND`
90
+ Literal values listed in the config reference ; Roadmap section
91
+ pruned of items that shipped in v0.4.0 (Composite adapter, XTypes
92
+ Cyclone push).
93
+ - **`docs/DDS_QUICKSTART.md`** — header bumped to v0.4.0+ ; §4
94
+ "Single-adapter limitation (v0.3.0)" replaced by "Composite adapter
95
+ (v0.4.0 Phase 1+)" with the new routing table ; §5 documents the
96
+ v0.4.0 Phase 1.5 best-effort XTypes story (no more
97
+ `AdapterError` on user topics) ; §6 "What's next" pruned of shipped
98
+ items ; §7 Troubleshooting updated.
99
+ - **`docs/TESTING.md`** — "five MCP tools" → "eleven MCP tools" in the
100
+ three documented occurrences ("Pick your path" table row, the lead
101
+ paragraph, Path 1 header). New v0.4.0 tool-surface callout above
102
+ the path picker.
103
+
104
+ #### Added (sub-milestone 5.3 — new docs and examples)
105
+
106
+ - **`docs/MIGRATION_v0.3_to_v0.4.md`** (new, sibling to the existing
107
+ `MIGRATION_v0.2_to_v0.3.md`). 8 sections : new tools, env vars and
108
+ extras, soft-breaking schema widening (`ParticipantInfo` +4 fields,
109
+ `BagAnalysis` +4 fields, `HealthReport.ros_backend`, `dds_backend`
110
+ widening, `AdapterName` widening, new `TopicMetrics` /
111
+ `ParticipantEvent` schemas), `CompositeAdapter`, `peek_dds_samples`
112
+ user-topic story, protocol expansions, plus a quick checklist.
113
+ - **`docs/TROUBLESHOOTING.md`** (new). One section per polished
114
+ AdapterError message, plus the cross-cutting "ROS2 CLI not found on
115
+ PATH" / `auto` fallback to mock case. Each section quotes the
116
+ message and lists the diagnostics in order.
117
+ - **`examples/`** (new). 4 mock-mode-runnable walkthroughs covering
118
+ the headline value props :
119
+ - `01-discover-ros2-stack.md` — `health_check` + `list_topics` +
120
+ `get_topic_info` + `sample_messages`
121
+ - `02-debug-qos-mismatch.md` — `list_participants` +
122
+ `detect_qos_mismatches` + `peek_dds_samples` (canonical
123
+ Reliability mismatch story)
124
+ - `03-analyze-recording.md` — `analyze_bag` + `peek_bag_samples`
125
+ post-mortem inspection
126
+ - `04-monitor-topic-frequency.md` — `topic_metrics` +
127
+ `participant_events` with the opportunistic-fill caveat
128
+ Each example pairs an MCP-client prompt with the expected tool
129
+ calls and a short LLM-facing synthesis.
130
+
131
+ #### Added (sub-milestone 5.3 — repo polish)
132
+
133
+ - **`CONTRIBUTING.md`** (new). What contributions land easily vs hard,
134
+ development setup, the `make check` contract, mock-first
135
+ development convention, layer separation, pure-parser convention,
136
+ commit conventions.
137
+ - **`SECURITY.md`** (new). Local-trust threat model, the
138
+ read-only-by-architecture stance, vulnerability disclosure email,
139
+ response SLAs, supported version policy.
140
+ - **`.github/ISSUE_TEMPLATE/bug_report.yml`** (new) — structured form
141
+ with version, mode, OS, Python, repro, env vars, troubleshooting
142
+ check.
143
+ - **`.github/ISSUE_TEMPLATE/feature_request.yml`** (new) —
144
+ problem-first framing, tier disambiguation (OSS / Pro), explicit
145
+ read-only-by-architecture acknowledgment.
146
+ - **`.github/ISSUE_TEMPLATE/config.yml`** (new) — disables blank
147
+ issues, links to `SECURITY.md`, `docs/TROUBLESHOOTING.md`,
148
+ `docs/DDS_QUICKSTART.md`.
149
+ - **`.github/PULL_REQUEST_TEMPLATE.md`** (new) — summary, test plan,
150
+ backward-compatibility checklist (covers the 11-tool cap, schema
151
+ additive-only invariant, telemetry 6-field contract, env var docs,
152
+ public API removal flag).
153
+
154
+ #### Notes
155
+
156
+ - **Backward compat preserved.** Zero schema changes, zero new tools,
157
+ zero env-var renames. The `DDS_ONLY_ERROR_MSG` substring tokens
158
+ pinned by existing tests (`"DDS observability only"`,
159
+ `"TOPICFORGE_DDS_BACKEND"`, `"TOPICFORGE_MODE"`) are preserved
160
+ intact ; v0.4.0 producers and clients keep working byte-for-byte.
161
+ - **CHANGELOG entry deferred to release time.** This branch leaves
162
+ `pyproject.toml` at `0.4.0`, `__version__` at `"0.4.0"`, and the
163
+ `## [Unreleased]` heading populated with the polish notes above.
164
+ The version bump and `v0.5.0` tag are the maintainer's manual
165
+ steps after final review.
166
+
167
+ ## [0.4.0] - 2026-05-15
9
168
 
10
169
  ### Sprint v0.4.0 — Phase 3 (bag analysis multi-format)
11
170
 
@@ -554,7 +713,9 @@ Initial MVP release of TopicForge — ROS Topic Inspector & Bag Analyzer MCP ser
554
713
  - The write path (publishing, commanding robots) is intentionally out of scope for the MVP.
555
714
  - `analyze_bag` in live mode parses `ros2 bag info` text output; deeper anomaly detection remains mock-only for now.
556
715
 
557
- [Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.3.0...HEAD
716
+ [Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.5.0...HEAD
717
+ [0.5.0]: https://github.com/yaniswav/TopicForge/compare/v0.4.0...v0.5.0
718
+ [0.4.0]: https://github.com/yaniswav/TopicForge/compare/v0.3.0...v0.4.0
558
719
  [0.3.0]: https://github.com/yaniswav/TopicForge/compare/v0.2.0...v0.3.0
559
720
  [0.2.0]: https://github.com/yaniswav/TopicForge/compare/v0.1.2...v0.2.0
560
721
  [0.1.2]: https://github.com/yaniswav/TopicForge/compare/v0.1.1...v0.1.2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topicforge
3
- Version: 0.4.0
3
+ Version: 0.5.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
@@ -37,6 +37,7 @@ Classifier: Operating System :: OS Independent
37
37
  Classifier: Programming Language :: Python :: 3
38
38
  Classifier: Programming Language :: Python :: 3.11
39
39
  Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Programming Language :: Python :: 3.13
40
41
  Requires-Python: >=3.11
41
42
  Requires-Dist: mcp>=1.0.0
42
43
  Requires-Dist: pydantic>=2.6
@@ -69,11 +70,12 @@ Description-Content-Type: text/markdown
69
70
  # TopicForge
70
71
 
71
72
  [![PyPI version](https://img.shields.io/pypi/v/topicforge.svg)](https://pypi.org/project/topicforge/)
73
+ [![CI](https://github.com/yaniswav/TopicForge/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/yaniswav/TopicForge/actions/workflows/ci.yml)
72
74
  [![Python versions](https://img.shields.io/pypi/pyversions/topicforge.svg)](https://pypi.org/project/topicforge/)
73
75
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/yaniswav/TopicForge/blob/main/LICENSE)
74
76
  [![Read-only by architecture](https://img.shields.io/badge/safety-read--only_by_architecture-2563eb)](https://github.com/yaniswav/TopicForge#security-model)
75
77
 
76
- > **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.
78
+ > **The safety-first read-only MCP for ROS2 robotics — observability + multi-vendor OMG DDS-RTPS (v0.4.0).** TopicForge lets AI agents inspect your ROS2 graph, recorded bag files, and the raw DDS layer beneath ROS — without ever publishing back to the bus. **Eleven typed read-only tools** (5 ROS2 graph + 3 DDS + 3 observability/bag) share a single Pydantic envelope so an LLM caller reads one schema across the whole stack. v0.4.0 adds participant lifecycle tracking (`participant_events`), temporal metrics (`topic_metrics`), and post-mortem bag sample peek (`peek_bag_samples`) on top of v0.3.0's two OSS Python DDS participants — Eclipse CycloneDDS and eProsima Fast DDS — each observing **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.
77
79
 
78
80
  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.
79
81
 
@@ -239,21 +241,24 @@ CoreDX, InterCOM) ship under the optional `topicforge-pro` package with
239
241
  BYO vendor license. See [`docs/pro.md`](docs/pro.md) for the early-access
240
242
  slot and pricing terms ; nothing is collected today.
241
243
 
242
- Three new MCP tools (in addition to the five ROS2 tools above) :
244
+ Six DDS / observability tools (in addition to the five ROS2 tools above) :
243
245
 
244
- | Tool | Purpose |
245
- | ----------------------- | -------------------------------------------------------------------------------- |
246
- | `list_participants` | DDS participants discovered on a domain, with vendor and hostname |
247
- | `detect_qos_mismatches` | Reader/writer QoS incompatibilities preventing communication on a topic |
248
- | `peek_dds_samples` | Recent samples on a raw DDS topic (distinct from `sample_messages` on ROS2 graph)|
246
+ | Tool | Since | Purpose |
247
+ | ----------------------- | ------- | -------------------------------------------------------------------------------------------------------------- |
248
+ | `list_participants` | v0.2.0 | DDS participants discovered on a domain, with vendor, hostname, and (v0.4.0) lifecycle fields |
249
+ | `detect_qos_mismatches` | v0.2.0 | Reader/writer QoS incompatibilities preventing communication on a topic |
250
+ | `peek_dds_samples` | v0.2.0 | Recent samples on a raw DDS topic — v0.4.0 adds best-effort XTypes user-topic decode (distinct from `sample_messages` on ROS2 graph) |
251
+ | `participant_events` | v0.4.0 | Lifecycle stream — `discovered` / `lost` participant events over a configurable window |
252
+ | `topic_metrics` | v0.4.0 | Temporal metrics — observed frequency, sequence gaps, latency p50/p95/p99 over a sliding window |
253
+ | `peek_bag_samples` | v0.4.0 | Post-mortem inspection — decoded samples from a recorded `.mcap` / `.db3` / `.bag` file |
249
254
 
250
- **Composite adapter (v0.4.0 Phase 1+).** When `TOPICFORGE_MODE=live` is paired with a DDS backend (`cyclone`, `fast`, …), TopicForge instantiates **both** a ROS2 CLI adapter and the chosen DDS adapter and routes per-tool category — the 5 ROS2 tools hit the CLI, the 3 DDS tools (+ `participant_events` from Phase 1) hit the DDS backend. ROS2-only or DDS-only setups still work — the missing half is skipped and the present half serves what it can. The mock backend continues to expose all 9 tools against deterministic fixtures for local development.
255
+ **Composite adapter (v0.4.0 Phase 1+).** When `TOPICFORGE_MODE=live` is paired with a DDS backend (`cyclone`, `fast`, …), TopicForge instantiates **both** a ROS2 CLI adapter and the chosen DDS adapter and routes per-tool category — the 5 ROS2 tools hit the CLI, the DDS / observability tools hit the DDS backend. ROS2-only or DDS-only setups still work — the missing half is skipped and the present half serves what it can. The mock backend continues to expose all 11 tools against deterministic fixtures for local development.
251
256
 
252
- **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.
257
+ **`peek_dds_samples` payload shape (v0.4.0 Phase 1.5).** Full-fidelity on the 4 builtin DCPS topics (`DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`). Arbitrary user topics return best-effort decoded samples with a `_decode_status` annotation : `"full"` (every IDL field decoded — currently a v0.4.0+ Cyclone XTypes path), `"partial"` (some fields decoded, others opaque), or `"raw"` (binding could not resolve the dynamic XTypes — bytes preserved as hex in `_raw_bytes_hex`). The diagnostic key `_decode_note` carries a short explanation when the status is non-`full`. The wire shape is identical across Cyclone and Fast backends.
253
258
 
254
259
  **`RTI Connext`** is v0.4.0+ Pro tier (BYO license — see `docs/pro.md`).
255
260
 
256
- **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).
261
+ **Full 5-minute walkthrough** — backend selection, the canonical QoS-mismatch debugging scenario, troubleshooting — lives in [`docs/DDS_QUICKSTART.md`](docs/DDS_QUICKSTART.md). Migration history : [v0.2 → v0.3](docs/MIGRATION_v0.2_to_v0.3.md), [v0.3 → v0.4](docs/MIGRATION_v0.3_to_v0.4.md).
257
262
 
258
263
  ### Configure with Claude Desktop
259
264
 
@@ -308,7 +313,7 @@ make check # both, plus tests (CI bundle)
308
313
  | `TOPICFORGE_LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
309
314
  | `TOPICFORGE_ROS2_BIN` | `ros2` | Name (or path) of the ROS2 CLI binary |
310
315
  | `TOPICFORGE_TELEMETRY` | `off` | Opt-in anonymous usage telemetry. See [Telemetry](#telemetry). |
311
- | `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). |
316
+ | `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `fast`, `rti`, `opensplice`, `coredx`, `intercom`, `opendds`, `dust`, or `auto`. The v0.4.0 Phase 1.5 auto-detect chain resolves to: `rti > opensplice > coredx > intercom` (Pro tier, if installed) `> opendds > fast > cyclone > dust > mock`. See [Multi-vendor DDS support](#multi-vendor-dds-support-v030). |
312
317
  | `TOPICFORGE_DDS_DOMAIN_ID` | `0` | DDS domain id observed (0..232) when a DDS backend is active. |
313
318
 
314
319
  See [`.env.example`](.env.example).
@@ -336,7 +341,7 @@ When telemetry is on, each MCP tool call emits a single event with **only** thes
336
341
 
337
342
  | Field | Example | Notes |
338
343
  | ----------------- | ---------------- | ---------------------------------------------------------------------- |
339
- | `tool_name` | `"list_topics"` | One of the five MVP tools — never argument values. |
344
+ | `tool_name` | `"list_topics"` | One of the eleven MCP tools — never argument values. |
340
345
  | `latency_ms` | `12.34` | Wall-clock duration of the handler, rounded to 2 decimals. |
341
346
  | `mode` | `"mock"` | Effective runtime mode: `mock` or `live`. |
342
347
  | `version` | `"0.1.2"` | TopicForge server version. |
@@ -382,16 +387,14 @@ See [`docs/product-plan.md`](docs/product-plan.md) for the full product trajecto
382
387
 
383
388
  Near-term additions on the bench:
384
389
 
385
- - `rclpy`-backed live adapter for faster & richer sampling
386
- - XTypes/IDL discovery to extend `peek_dds_samples` to arbitrary user topics (today: 4 builtin DCPS topics only) — v0.3.x patch
387
- - Extended QoS coverage (Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget) — v0.3.x patch
388
- - Composite adapter delegating per-tool category, so ROS2 + DDS surfaces work simultaneously — v0.3.x patch
389
- - `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`) — v0.4.0+
390
- - URDF inspector / validator MCP tools
391
- - Bag anomaly detection (clock jumps, gaps, dropped frames, TF tree health)
390
+ - `rclpy`-backed live adapter for faster & richer sampling (per-message rmw receive timestamps, windowed sampling) — gated on external user demand
391
+ - Extended QoS coverage (Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget) — v0.5.x patch
392
+ - Real `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`) — the v0.4.0 Phase 1.5 framework is in place ; production binding pending Pro tier launch
393
+ - URDF inspector / validator MCP tools (Pro tier)
394
+ - Bag anomaly detection (clock jumps, gaps, dropped frames, TF tree health) — Pro tier
392
395
  - Dataset export helpers (rosbag → COCO / HF Datasets)
393
396
  - Synthetic data pipeline controller (Blender, Gazebo, Isaac Sim)
394
- - Hosted MCP endpoint with auth
397
+ - Hosted MCP endpoint with auth (Phase 3 — depends on Pro tier traction)
395
398
 
396
399
  ## Project layout
397
400
 
@@ -1,11 +1,12 @@
1
1
  # TopicForge
2
2
 
3
3
  [![PyPI version](https://img.shields.io/pypi/v/topicforge.svg)](https://pypi.org/project/topicforge/)
4
+ [![CI](https://github.com/yaniswav/TopicForge/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/yaniswav/TopicForge/actions/workflows/ci.yml)
4
5
  [![Python versions](https://img.shields.io/pypi/pyversions/topicforge.svg)](https://pypi.org/project/topicforge/)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/yaniswav/TopicForge/blob/main/LICENSE)
6
7
  [![Read-only by architecture](https://img.shields.io/badge/safety-read--only_by_architecture-2563eb)](https://github.com/yaniswav/TopicForge#security-model)
7
8
 
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
+ > **The safety-first read-only MCP for ROS2 robotics — observability + multi-vendor OMG DDS-RTPS (v0.4.0).** TopicForge lets AI agents inspect your ROS2 graph, recorded bag files, and the raw DDS layer beneath ROS — without ever publishing back to the bus. **Eleven typed read-only tools** (5 ROS2 graph + 3 DDS + 3 observability/bag) share a single Pydantic envelope so an LLM caller reads one schema across the whole stack. v0.4.0 adds participant lifecycle tracking (`participant_events`), temporal metrics (`topic_metrics`), and post-mortem bag sample peek (`peek_bag_samples`) on top of v0.3.0's two OSS Python DDS participants — Eclipse CycloneDDS and eProsima Fast DDS — each observing **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
10
 
10
11
  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
12
 
@@ -171,21 +172,24 @@ CoreDX, InterCOM) ship under the optional `topicforge-pro` package with
171
172
  BYO vendor license. See [`docs/pro.md`](docs/pro.md) for the early-access
172
173
  slot and pricing terms ; nothing is collected today.
173
174
 
174
- Three new MCP tools (in addition to the five ROS2 tools above) :
175
+ Six DDS / observability tools (in addition to the five ROS2 tools above) :
175
176
 
176
- | Tool | Purpose |
177
- | ----------------------- | -------------------------------------------------------------------------------- |
178
- | `list_participants` | DDS participants discovered on a domain, with vendor and hostname |
179
- | `detect_qos_mismatches` | Reader/writer QoS incompatibilities preventing communication on a topic |
180
- | `peek_dds_samples` | Recent samples on a raw DDS topic (distinct from `sample_messages` on ROS2 graph)|
177
+ | Tool | Since | Purpose |
178
+ | ----------------------- | ------- | -------------------------------------------------------------------------------------------------------------- |
179
+ | `list_participants` | v0.2.0 | DDS participants discovered on a domain, with vendor, hostname, and (v0.4.0) lifecycle fields |
180
+ | `detect_qos_mismatches` | v0.2.0 | Reader/writer QoS incompatibilities preventing communication on a topic |
181
+ | `peek_dds_samples` | v0.2.0 | Recent samples on a raw DDS topic — v0.4.0 adds best-effort XTypes user-topic decode (distinct from `sample_messages` on ROS2 graph) |
182
+ | `participant_events` | v0.4.0 | Lifecycle stream — `discovered` / `lost` participant events over a configurable window |
183
+ | `topic_metrics` | v0.4.0 | Temporal metrics — observed frequency, sequence gaps, latency p50/p95/p99 over a sliding window |
184
+ | `peek_bag_samples` | v0.4.0 | Post-mortem inspection — decoded samples from a recorded `.mcap` / `.db3` / `.bag` file |
181
185
 
182
- **Composite adapter (v0.4.0 Phase 1+).** When `TOPICFORGE_MODE=live` is paired with a DDS backend (`cyclone`, `fast`, …), TopicForge instantiates **both** a ROS2 CLI adapter and the chosen DDS adapter and routes per-tool category — the 5 ROS2 tools hit the CLI, the 3 DDS tools (+ `participant_events` from Phase 1) hit the DDS backend. ROS2-only or DDS-only setups still work — the missing half is skipped and the present half serves what it can. The mock backend continues to expose all 9 tools against deterministic fixtures for local development.
186
+ **Composite adapter (v0.4.0 Phase 1+).** When `TOPICFORGE_MODE=live` is paired with a DDS backend (`cyclone`, `fast`, …), TopicForge instantiates **both** a ROS2 CLI adapter and the chosen DDS adapter and routes per-tool category — the 5 ROS2 tools hit the CLI, the DDS / observability tools hit the DDS backend. ROS2-only or DDS-only setups still work — the missing half is skipped and the present half serves what it can. The mock backend continues to expose all 11 tools against deterministic fixtures for local development.
183
187
 
184
- **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.
188
+ **`peek_dds_samples` payload shape (v0.4.0 Phase 1.5).** Full-fidelity on the 4 builtin DCPS topics (`DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`). Arbitrary user topics return best-effort decoded samples with a `_decode_status` annotation : `"full"` (every IDL field decoded — currently a v0.4.0+ Cyclone XTypes path), `"partial"` (some fields decoded, others opaque), or `"raw"` (binding could not resolve the dynamic XTypes — bytes preserved as hex in `_raw_bytes_hex`). The diagnostic key `_decode_note` carries a short explanation when the status is non-`full`. The wire shape is identical across Cyclone and Fast backends.
185
189
 
186
190
  **`RTI Connext`** is v0.4.0+ Pro tier (BYO license — see `docs/pro.md`).
187
191
 
188
- **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).
192
+ **Full 5-minute walkthrough** — backend selection, the canonical QoS-mismatch debugging scenario, troubleshooting — lives in [`docs/DDS_QUICKSTART.md`](docs/DDS_QUICKSTART.md). Migration history : [v0.2 → v0.3](docs/MIGRATION_v0.2_to_v0.3.md), [v0.3 → v0.4](docs/MIGRATION_v0.3_to_v0.4.md).
189
193
 
190
194
  ### Configure with Claude Desktop
191
195
 
@@ -240,7 +244,7 @@ make check # both, plus tests (CI bundle)
240
244
  | `TOPICFORGE_LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
241
245
  | `TOPICFORGE_ROS2_BIN` | `ros2` | Name (or path) of the ROS2 CLI binary |
242
246
  | `TOPICFORGE_TELEMETRY` | `off` | Opt-in anonymous usage telemetry. See [Telemetry](#telemetry). |
243
- | `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). |
247
+ | `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `fast`, `rti`, `opensplice`, `coredx`, `intercom`, `opendds`, `dust`, or `auto`. The v0.4.0 Phase 1.5 auto-detect chain resolves to: `rti > opensplice > coredx > intercom` (Pro tier, if installed) `> opendds > fast > cyclone > dust > mock`. See [Multi-vendor DDS support](#multi-vendor-dds-support-v030). |
244
248
  | `TOPICFORGE_DDS_DOMAIN_ID` | `0` | DDS domain id observed (0..232) when a DDS backend is active. |
245
249
 
246
250
  See [`.env.example`](.env.example).
@@ -268,7 +272,7 @@ When telemetry is on, each MCP tool call emits a single event with **only** thes
268
272
 
269
273
  | Field | Example | Notes |
270
274
  | ----------------- | ---------------- | ---------------------------------------------------------------------- |
271
- | `tool_name` | `"list_topics"` | One of the five MVP tools — never argument values. |
275
+ | `tool_name` | `"list_topics"` | One of the eleven MCP tools — never argument values. |
272
276
  | `latency_ms` | `12.34` | Wall-clock duration of the handler, rounded to 2 decimals. |
273
277
  | `mode` | `"mock"` | Effective runtime mode: `mock` or `live`. |
274
278
  | `version` | `"0.1.2"` | TopicForge server version. |
@@ -314,16 +318,14 @@ See [`docs/product-plan.md`](docs/product-plan.md) for the full product trajecto
314
318
 
315
319
  Near-term additions on the bench:
316
320
 
317
- - `rclpy`-backed live adapter for faster & richer sampling
318
- - XTypes/IDL discovery to extend `peek_dds_samples` to arbitrary user topics (today: 4 builtin DCPS topics only) — v0.3.x patch
319
- - Extended QoS coverage (Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget) — v0.3.x patch
320
- - Composite adapter delegating per-tool category, so ROS2 + DDS surfaces work simultaneously — v0.3.x patch
321
- - `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`) — v0.4.0+
322
- - URDF inspector / validator MCP tools
323
- - Bag anomaly detection (clock jumps, gaps, dropped frames, TF tree health)
321
+ - `rclpy`-backed live adapter for faster & richer sampling (per-message rmw receive timestamps, windowed sampling) — gated on external user demand
322
+ - Extended QoS coverage (Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget) — v0.5.x patch
323
+ - Real `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`) — the v0.4.0 Phase 1.5 framework is in place ; production binding pending Pro tier launch
324
+ - URDF inspector / validator MCP tools (Pro tier)
325
+ - Bag anomaly detection (clock jumps, gaps, dropped frames, TF tree health) — Pro tier
324
326
  - Dataset export helpers (rosbag → COCO / HF Datasets)
325
327
  - Synthetic data pipeline controller (Blender, Gazebo, Isaac Sim)
326
- - Hosted MCP endpoint with auth
328
+ - Hosted MCP endpoint with auth (Phase 3 — depends on Pro tier traction)
327
329
 
328
330
  ## Project layout
329
331
 
@@ -1,4 +1,4 @@
1
- # DDS quickstart — TopicForge v0.3.0+
1
+ # DDS quickstart — TopicForge v0.4.0+
2
2
 
3
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
4
 
@@ -99,25 +99,25 @@ The analyzer covers the four MVP policies — **Reliability**, **Durability**, *
99
99
 
100
100
  ---
101
101
 
102
- ## 4. Single-adapter limitation (v0.3.0)
102
+ ## 4. Composite adapter (v0.4.0 Phase 1+)
103
103
 
104
- TopicForge v0.3.0 still selects **one adapter at a time** based on `TOPICFORGE_MODE` + `TOPICFORGE_DDS_BACKEND` :
104
+ v0.4.0 Phase 1 lifted the v0.3.0 single-adapter limitation. When `TOPICFORGE_MODE=live` is paired with a DDS backend, TopicForge instantiates **both** a `Ros2CliAdapter` and the chosen DDS adapter behind a `CompositeAdapter` and routes per-tool category — the 5 ROS2 graph tools hit the CLI, the 6 DDS / observability tools (`list_participants`, `detect_qos_mismatches`, `peek_dds_samples`, `participant_events`, `topic_metrics`, `peek_bag_samples`) hit the DDS half. The `name` collapses to `"ros2_cli+cyclone"` or `"ros2_cli+fast"` ; `effective_mode` reports `"live"` whenever either half is live.
105
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) |
106
+ | `TOPICFORGE_MODE` | `TOPICFORGE_DDS_BACKEND` | Active adapter | ROS2 tools | DDS / observability tools |
107
+ | ----------------- | ------------------------ | ----------------------------- | -------------------------------- | ----------------------------------- |
108
+ | `mock` | (any) | `MockAdapter` | work (fixtures) | work (fixtures) |
109
+ | `live` / `auto` | `mock` (default) | `Ros2CliAdapter` | work | raise with remediation |
110
+ | `live` / `auto` | `cyclone` | `CompositeAdapter(ros2_cli + cyclone)` | work (CLI) | work (real CycloneDDS) |
111
+ | `live` / `auto` | `fast` | `CompositeAdapter(ros2_cli + fast)` | work (CLI) | work (real Fast DDS) |
112
+ | `live` / `auto` | `rti` | falls back to `Ros2CliAdapter` | work (CLI) | raise (v0.4.0+ Pro tier — BYO license) |
113
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.
114
+ **Graceful degradation paths preserved.** DDS binding missing → ROS2-CLI-only (the v0.3.0 behavior). ROS2 CLI missing on PATH → DDS-only adapter with a clear `DDS_ONLY_ERROR_MSG` on the 5 ROS2 methods. Neither available → MockAdapter (auto mode only).
115
115
 
116
- Error messages on the unselected side are explicit and point at the remediation path — no silent failures.
116
+ `HealthReport` reports both halves via the `ros_backend` and `dds_backend` fields, so a downstream client can introspect which half of a composite is live without guessing.
117
117
 
118
118
  ---
119
119
 
120
- ## 5. v0.3.0 scope of `peek_dds_samples`
120
+ ## 5. v0.4.0 scope of `peek_dds_samples`
121
121
 
122
122
  `peek_dds_samples` is full-fidelity on the 4 builtin DCPS topics with both backends :
123
123
 
@@ -127,18 +127,26 @@ peek_dds_samples(topic="DCPSSubscription", count=10)
127
127
  peek_dds_samples(topic="DCPSPublication", count=10)
128
128
  ```
129
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.
130
+ **Arbitrary user topics (v0.4.0 Phase 1.5+).** The v0.3.0 `AdapterError` is retired. The tool now returns best-effort decoded samples annotated with a `_decode_status` field :
131
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.
132
+ - `"full"` — every IDL field decoded (currently the Cyclone XTypes path, structurally in place ; real-bus validation pending user feedback)
133
+ - `"partial"` — some fields decoded, others opaque (mixed-success path)
134
+ - `"raw"` — the binding could not resolve the dynamic XTypes ; the serialized payload is preserved as hex in `_raw_bytes_hex` (capped at 4096 hex chars ; `_raw_bytes_truncated=True` flags clipping)
135
+
136
+ The diagnostic key `_decode_note` carries a short explanation when the status is non-`full`. The wire shape is identical across Cyclone and Fast DDS — the analyzer doesn't need to know which backend produced the sample.
137
+
138
+ Fast DDS 2.6.x exposes only a partial dynamic XTypes Python surface today, so the `"raw"` fallback is the common path on Fast DDS user topics — the structural plumbing is identical to Cyclone, the upstream binding completion is the gating factor.
139
+
140
+ The other DDS tools — `list_participants`, `detect_qos_mismatches`, `participant_events`, `topic_metrics` — work end-to-end on any user-topic deployment ; they don't depend on payload deserialization.
133
141
 
134
142
  ---
135
143
 
136
144
  ## 6. What's next
137
145
 
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`).
146
+ - **v0.5.x patch** — Fast DDS XTypes binding completion to lift `"raw"` → `"full"` for arbitrary user-topic peek on Fast.
147
+ - **v0.5.x patch** — Extended QoS coverage : Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget.
148
+ - **v0.5.x patch** — Real-bus validation of the Cyclone XTypes pipeline (the v0.4.0 Phase 1.5 structural pipeline awaits user feedback on real domains).
149
+ - **v0.4.0+ Pro tier** — Real `RtiConnextAdapter` (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`). Scaffolded but not yet shipped.
142
150
 
143
151
  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
152
 
@@ -149,8 +157,9 @@ Full strategic roadmap lives in [`docs/product-plan.md`](product-plan.md) and th
149
157
  - **`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
158
  - **`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
159
  - **`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.
160
+ - **DDS tool returns samples with `_decode_status="raw"`** — the binding could not resolve the dynamic XTypes for this user topic. Inspect `_decode_note` for the cause and `_raw_bytes_hex` for the serialized payload. On Fast DDS this is the common path until 2.6.x dynamic XTypes binding completion. On Cyclone, ensure the publisher uses XTypes-discoverable types and re-run.
161
+ - **DDS tool returns "DDS module is not active" error** — your `TOPICFORGE_DDS_BACKEND` is `mock` while `TOPICFORGE_MODE` is `live` (the ROS2 CLI half of the composite is the only one selected). Set `TOPICFORGE_DDS_BACKEND=cyclone` or `=fast` explicitly to enable the DDS half — the `CompositeAdapter` will then serve both surfaces.
162
+ - **DDS tool returns "DDS observability only" with a long remediation message** — the inverse case: a DDS-only adapter is active (the ROS2 CLI is missing on PATH) and you called a ROS2 graph tool. Install ROS2 and source the workspace so `ros2` is on PATH ; the `CompositeAdapter` will pick up both halves on the next run.
154
163
  - **`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
164
 
156
165
  Report issues at https://github.com/yaniswav/TopicForge/issues.