Releases: yaniswav/TopicForge
Release list
TopicForge 0.5.6
Fixes from a live run of 0.5.3 and 0.5.5 against OmniSim's simulated
Clearpath Husky (ROS 2 Humble, Fast DDS, Cyclone backend for the DDS tools),
reported with ground truth by the OmniSim team.
Added
sample_messagestakesmax_array_length(1..65536, default 128, null for no
cut) andarrays_summary_only. A cut is listed under_truncated_after_columns
in the sample and innote.- Size caps on returned samples: 1 MiB per message and 4 MiB per call
(TOPICFORGE_MAX_SAMPLE_BYTESsets the per-message cap). Over-cap messages are
dropped andnotesays so.peek_bag_samplesis capped the same way, and its
arrays are cut at 4096 elements. BagTopicStatsgainsfirst_timestamp_ns,last_timestamp_ns,
frequency_basis(topic_spanorbag_duration) andlatched.TopicInfo.qos_durability;qos_reliabilityandqos_durabilityare filled
byget_topic_infofrom the publishers' QoS (mixedwhen they disagree).HealthReport.dds_inactive_reasonsays whydds_backendisnone.- A real Humble rosbag2 bag from the OmniSim team as a test fixture
(tests/fixtures/bags/omnisim_humble/).
Changed
list_topics(live) uses oneros2 topic list -vcall for publisher and
subscriber counts instead of oneros2 topic infoper topic, falling back to
the per-topic calls if the output is not recognized. It leaves QoS null.rosbags>=0.11.3is required (0.10 reads a bare.db3as ROS 1 and returns
message definitions and QoS as plain strings).- A latched topic gets no rate only when its messages span under 1 second (a
start-up burst such as/tf_static); a latched topic published over a longer
span keeps its rate.latchedis unchanged. analyze_bagreads per-topic times of an.mcapbag only up to 200 MiB and
5 s; past either it keepsbag_durationrates and says so in the new
BagAnalysis.note.- The
policies_checkedentry for History reads "History (risky only, where
announced)". max_array_lengthalso cuts strings and bytes to that many characters plus
...; those cells are listed under_truncated_columns.QosProfile.historyis now optional, and a newhistory_noteexplains why it
is missing. DDS discovery does not carry History (the builtin endpoint data has
no such member), so TopicForge reports it only for its own endpoints and for
Cyclone DDS peers that set something other than the default. For Fast DDS, RTI
and unknown-vendor endpoints it isnull; for a Cyclone peer, KEEP_LAST depth 1
is alsonullbecause the binding fills missing QoS with that default. Clients
that assumedhistoryis always a string must handlenull.- A discovered endpoint that announced no History keeps its reliability,
durability and the other policies; before, the wholeqosbecamenull. detect_qos_mismatchesjudges the KEEP_ALL-vs-KEEP_LAST History risk only
where both sides announced History; elsewhere one hint states that discovery
does not carry it, instead of a warning on every pair.
Fixed
sample_messageswitharrays_summary_onlyshifted every CSV column after an
array:<sequence type: float, length: 541>contains a comma and was split in
two. It is one cell now.sample_messagesreturned no samples and no explanation when the echo timed
out (for example a large message withmax_array_lengthnull);notenow says
so.list_topicsreported 0 publishers and 0 subscribers for a topic missing from
ros2 topic list -v; it now asksros2 topic infofor that topic.peek_bag_samplesconverted a whole numpy array to a list before cutting it
at 4096 elements; it now converts only the part it keeps.- Fast DDS endpoints no longer report a History taken from the binding's
defaults:detect_qos_mismatchestreats it as not announced, like the other
vendors. This path has never run against a real Fast DDS bus. - The
tests/fixtures/bagsbag is left out of the sdist. peek_bag_samplesfailed on every Humble.db3bag with "Bag contains no
type definitions". The reader now gets the type definitions of the distro the
bag records, or Humble, andnotesays which.LaserScan.rangesand other
numeric arrays now come back as lists, not a numpy repr string.analyze_bagrates were count / whole-bag duration, 0.1 to 0.7 percent off on
periodic topics and meaningless on latched ones (/tf_staticshowed 0.06 Hz,
/rosout0.37 Hz). They are now(n - 1) / (last - first)per topic, read
from the bag when it is readable locally, and latched topics are flagged.get_topic_inforeturnedqos_reliability: nullon every topic although the
CLI prints Reliability and Durability per endpoint.peek_dds_samples('/scan')reported the topic as not discovered while
rt/scanandscanworked; it now resolves the name like the other DDS tools
and says which topic matched.- The "DDS module is not active" error said to install the Cyclone binding even
when it was installed. It now states the actual cause: backend not selected,
binding missing, or adapter failed to start. README wording aligned. - CSV
...truncation cells fromros2 topic echono longer count as data
columns. ros2output is decoded as UTF-8 on Windows instead of cp1252.detect_qos_mismatchesno longer calls service, action,rosout,
parameter_eventsorros_discovery_infotopics typos of each other (for
exampleget_parametersRequestvsset_parametersRequest), and no longer
reports them as orphans. Only plainrt/topics and bare DDS names are compared.- The "differs by N edits" hint is now only given between a writer-only name and
a reader-only name; a topic with both sides is never suggested as a typo.
TopicForge 0.5.5
Tool outputs were reworked after testing them with LLM agents on the author's
16 test scenarios (live DDS buses with planted faults).
Breaking
detect_qos_mismatchesreturns aMismatchScanenvelope instead of a bare
list. Migrate by reading["reports"]where you used the list.
Added
list_endpoints, the twelfth tool: every announced DDS writer and reader with
owning participant, structured QoS and a per-topic roll-up that flags orphans
(no_reader,no_writer). Cyclone and mock only.- Continuous discovery tracking on Cyclone, so a node restarted three times
shows as 3lostand 4discoveredevents dated by DDS, not by poll time. announced_ns,lost_ns,time_sourceand related timestamp fields on
participant_eventsandlist_participants.health_checkreportsnow_ns, tracker status and an observed-domain note.QosProfilegains Liveliness, Ownership, Partition, LatencyBudget,
DestinationOrder and DataRepresentation.peek_dds_sampleson builtin discovery topics returns structured endpoint
and participant fields instead of a raw repr string.- Topic filters accept
rt/xandxinterchangeably; a filter that matches
nothing returns the known topics. detect_qos_mismatchesalso reportsmatchedandnot_matchedpairs, hints
(near-miss topic names, path suffixes, type id differences), and the policies
it did and did not check.
Changed
detect_qos_mismatcheschecks Partition first (with*and?wildcards),
then type names, then the RxO rules; Liveliness, LatencyBudget, Ownership,
DestinationOrder and DataRepresentation join Reliability, Durability and
Deadline.topic_metricsandpeek_dds_sampleson a user topic say they have no data
instead of returning zeros or a placeholder.- Tool descriptions no longer carry internal history.
Fixed
- Infinite durations are
Noneinstead of 9223372036854775807. - Races between the tracker and tool calls could mark a live participant lost
or keep endpoints of a departed one. - Concurrent cyclonedds calls could corrupt the heap on Windows; every binding
call now takes one lock. - A failing tracker no longer adds 3 s to every tool call.
- An unreadable QoS duration is treated as unknown, not infinite.
- Typo hints stay bounded on a bus with a thousand topics.
Known limits
- A hung writer (alive, no data) cannot be observed without a data probe.
- A crash and a clean leave look the same;
lost_nsis an upper bound. - A participant that cycles faster than the history depth between two tracker
passes can be missed. - The Fast DDS backend has never run on a bus;
list_endpointsis not
supported there. - DDS Security is not supported, and user-topic payload decoding is disabled.
TopicForge 0.5.4
First run of the DDS code against a live bus (Windows 11, a Python / Cyclone DDS
participant and a Rust / Dust DDS participant). It exposed four defects that
left the DDS module non-functional on Cyclone; all are fixed and tested.
Fixed
list_participantsreports the participant name and hostname on Cyclone
(both were always null).- Participant GUIDs were never read, so every participant collapsed onto one
unknownentry. - Vendors were never identified. The vendor id is now read from the GUID prefix;
Dust DDS and RTI by default still reportunknown. - The OMG vendor-id table mapped Fast DDS and Cyclone to the wrong ids (now
01.0Fand01.10). The Fast DDS side is verified statically only. ParticipantInfo.vendoralso acceptsrti_micro,opensplice,opendds,
coredx,intercomanddust.detect_qos_mismatchesnever reported anything on Cyclone because policy
class names were not normalized.- A stopped participant never disappeared; departed participants and endpoints
are now dropped. - The Cyclone adapter leaked a reader per tool call and waited 2 s each; it now
keeps one reader per builtin topic. peek_dds_samplesonDCPSPublication/DCPSSubscriptionlisted endpoints
of participants that had left, and now includes the endpointtype_name.- Example role nodes published below their rate on Windows.
Added
examples/dds/: fourteen runnable examples (concepts and use cases), all
passing on a live bus.scripts/integration/: a demo driver, twelve interop programs (Cyclone, Dust,
Fast DDS, RTI, OpenSplice), one-command setup scripts and CI workflows. Only
Cyclone Python and Dust Rust / Python / C have been run, on Windows.
Removed
- The docker / scenario integration rig, replaced by the demo driver.
TopicForge 0.5.3
Fixes from an independent review of the whole repository, including a supply-chain issue. Upgrade recommended.
Security
- Extras depended on package names that do not exist on PyPI.
fastdds(in[dds],[dds-fast],[all],[dds-all-oss]) anddust-dds-python(in[dds-dust]) are not registered, so the documentedpip install topicforge[dds]failed, and anyone could have published those names to run code on install. Only extras whose packages exist remain:[dds-cyclone],[dds](Cyclone only),[bags],[all]. Versions 0.3.0 to 0.5.2 are affected and have been yanked from PyPI. - Removed the automatic
topicforge_proplugin hook, which imported any package by that (unclaimed) name at startup and gave it the full MCP server, enough to register write tools.
Fixed
health_checknow reports the adapter actually running. It used to saylivewhile serving mock fixtures whenros2was missing.- An explicit
TOPICFORGE_DDS_BACKENDis honoured without theros2CLI instead of silently serving fixtures. autono longer picks the OpenDDS/Dust stubs, which made it lose the real Cyclone backend.- A broken DDS environment no longer crashes startup.
- Every Cyclone read is bounded (an unbounded read could hang the server on an active topic).
topic_metricsno longer counts samples that were never received.
Changed
- Payload decoding of user DDS topics is disabled. It never worked on either backend, and cannot be validated without a live bus.
peek_dds_samplesreports that a topic is present without decoding it; the three builtin discovery topics are unaffected. - Python 3.10 is supported, so ROS 2 Humble (Ubuntu 22.04) users can install it.
- Tool descriptions read by the LLM corrected;
topic_metricsstates its real limits.
Breaking
TOPICFORGE_DDS_BACKENDno longer acceptsrti,opensplice,coredx,intercom. RTI and other vendors are still observed on the bus through standard discovery.- Extras
[dds-fast],[dds-opendds],[dds-dust],[dds-all-oss]removed. Fast DDS still works once its Python binding is built from eProsima's sources.
Correction
- The 0.5.1 notes said sequence gaps are counted per writer. No adapter provides the writer identity, so that statement was wrong.
pip install --upgrade topicforge==0.5.3Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#053---2026-10-01
TopicForge 0.5.2
Documentation and metadata only. No code, no schema, no dependency changes; install behaviour is identical to 0.5.1.
Added
server.json: MCP Registry metadata. Declares the server asio.github.yaniswav/topicforgeand points at the PyPI package, with the four user-facing environment variables documented so MCP clients can render configuration hints. Validated against the registry's published JSON schema.- PyPI ownership marker in
README.md: the registry verifies ownership of a PyPI package by looking for anmcp-namestring in the package description, which is generated from the README at build time. The marker is an HTML comment, so it does not render.
Why this release exists
The marker only reaches PyPI when a distribution is built and published. 0.5.1 shipped before the marker was added, so its published description does not carry it and registry validation would reject the submission. Cutting this version is the mechanical prerequisite for listing TopicForge in the official MCP Registry. There is no functional change to install.
pip install topicforge==0.5.2Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#052---2026-08-22
TopicForge 0.5.1
Hotfix: restores installability, plus the external-audit backlog (Lots 0-5, 2026-07-08) that had been sitting under [Unreleased].
Fixed: installability
- Hard-pinned
mcp < 2. TopicForge was uninstallable viapip install topicforgefrom 2026-07-28 to 2026-08-22: the MCP Python SDK's2.0.0release removed themcp.server.fastmcpmodule thatserver/app.pyimports, and the dependency was declared as an unboundedmcp>=1.0.0, so every fresh install resolved to the broken SDK version. Migrating to the 2.x API is tracked separately and is not part of this fix.
Fixed: DDS correctness (external audit)
topic_metrics: frequency was computed over the wrong time span and off-by-one interval count; a single opportunistic peek now correctly reportsfrequency_hz_observed = nullinstead of a fabricated rate.topic_metrics: sequence-gap counting is now per-writer, so multi-writer topics, publisher restarts, and counter wraps no longer inflate the gap count.detect_qos_mismatches: a reader requesting a finite QoS Deadline against a writer offering none is now correctly flagged as incompatible (previously a false negative).LifecycleBufferandMetricsBufferparticipant/topic maps are now bounded (capped at 4096 entries each, oldest evicted first); previously unbounded on a long-running, churny bus.- Several smaller correctness fixes: OpenDDS stub no longer misreports availability, a string
__slots__no longer gets exploded character-by-character during decoding, decode recursion is depth-capped, and raw payload preview is sliced before hex-encoding rather than after.
Changed
- Cyclone discovery/sample reads switched from destructive
take_iterto non-destructiveread_iter, the correct choice for a read-only observer. This change is validated by static analysis only (ruff+py_compile); it has not yet been exercised against a real multi-vendor DDS bus. Real-bus validation remains open. - QoS-mismatch pairing logic deduplicated into a shared, unit-tested module instead of ~40 duplicated lines per adapter.
Docs
- New
docs/TUTORIEL.md: English tutorial with a mock-mode quickstart, the eleven-tool table, advanced options, copy-pasteable scheduled-task prompts, and the telemetry privacy contract. docs/product-plan.mdrealigned on the shipped 11-tool surface;peek_dds_samplesdocumentation corrected on what therawdecode fallback actually preserves.
pip install topicforge==0.5.1Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#051---2026-08-22
TopicForge 0.5.0
Polish and validation pass ahead of marketing publication. No new tools, no schema changes.
Highlights
- CI matrix expanded from Ubuntu-only to Ubuntu + Windows across Python 3.11-3.13, closing the largest previously hand-validated surface (TopicForge's primary dev environment is Windows).
AdapterErrormessages rewritten across the DDS adapters and bag service with concrete diagnostics (exception type, domain id, topic name, likely causes) instead of generic wording.- New docs: a v0.3 to v0.4 migration guide, a troubleshooting guide indexed by error message, four runnable mock-mode examples,
CONTRIBUTING.md,SECURITY.md, and issue/PR templates. - Internal audit-followup tracker refreshed; three previously-open items closed.
Compatibility
- Zero schema changes, zero new tools, zero env-var renames. Existing producers and clients continue to work unchanged.
pip install topicforge==0.5.0Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#050---2026-05-21
TopicForge 0.4.0
The DDS observability release: participant lifecycle tracking, per-topic metrics, and multi-format bag analysis, taking the read-only tool surface from eight to eleven tools.
Highlights
- New participant lifecycle tracking (discovered/lost events) and a composite adapter that serves ROS2 and DDS tools from a single live process.
peek_dds_samplescan now decode arbitrary user-defined DDS topics (not just the builtin discovery topics), reporting a full/partial/raw decode status per sample.- DDS backend auto-detection now probes eight vendor bindings in priority order and falls back to mock when none are present.
- New per-topic metrics tool: observed frequency, sequence-gap count, and latency percentiles. Caveat carried into the tool description: neither the Cyclone nor Fast DDS Python bindings expose sample-receive callbacks, so metrics only accumulate opportunistically, as
peek_dds_samplesis called on that topic. analyze_bagenriched with format detection, recording duration, and embedded-participant info; a new tool peeks decoded samples directly out of a recorded bag file for post-mortem inspection.- A real-bus integration test rig (Docker Compose, per-vendor publisher scripts) was added for maintainer validation; it runs on a manually-triggered CI workflow, not on every push.
Known limitations
- OpenDDS and Dust DDS adapters ship as stubs: neither vendor has a usable PyPI Python binding yet, so their optional install extras (
pip install topicforge[dds-opendds]/[dds-dust]) are expected to fail today; they exist to anchor auto-detection for when upstream ships. - Cyclone's dynamic XTypes decode path is best-effort and falls back to raw bytes on failure; Fast DDS's equivalent path is not yet functional pending upstream binding support.
pip install topicforge==0.4.0Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#040---2026-05-15
TopicForge 0.3.0
TopicForge v0.3.0: OMG-standard multi-vendor DDS support
- CycloneDdsAdapter real implementation (replaces v0.2.0 stub)
- FastDdsAdapter new (Apache 2.0, default for ROS2 Humble)
- MiddlewareAdapter protocol exposes OMG concepts only, no vendor leak
- TOPICFORGE_DDS_BACKEND accepts mock|cyclone|fast|auto|rti
- Auto resolution chain: RTI Pro > Fast > Cyclone > Mock
- 203 tests pass, 22 skipped (cross-vendor without SDK)
- Bugfix v0.2.0: HealthService.report() now populates DDS fields
- See docs/dds-interop-matrix.md for OMG validation context
- See docs/MIGRATION_v0.2_to_v0.3.md for soft-breaking changes
TopicForge 0.2.0
TopicForge v0.2.0: safety-first read-only DDS support