Skip to content

Releases: yaniswav/TopicForge

TopicForge 0.5.6

Choose a tag to compare

@yaniswav yaniswav released this 02 Oct 18:53
19161fc

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_messages takes max_array_length (1..65536, default 128, null for no
    cut) and arrays_summary_only. A cut is listed under _truncated_after_columns
    in the sample and in note.
  • Size caps on returned samples: 1 MiB per message and 4 MiB per call
    (TOPICFORGE_MAX_SAMPLE_BYTES sets the per-message cap). Over-cap messages are
    dropped and note says so. peek_bag_samples is capped the same way, and its
    arrays are cut at 4096 elements.
  • BagTopicStats gains first_timestamp_ns, last_timestamp_ns,
    frequency_basis (topic_span or bag_duration) and latched.
  • TopicInfo.qos_durability; qos_reliability and qos_durability are filled
    by get_topic_info from the publishers' QoS (mixed when they disagree).
  • HealthReport.dds_inactive_reason says why dds_backend is none.
  • A real Humble rosbag2 bag from the OmniSim team as a test fixture
    (tests/fixtures/bags/omnisim_humble/).

Changed

  • list_topics (live) uses one ros2 topic list -v call for publisher and
    subscriber counts instead of one ros2 topic info per topic, falling back to
    the per-topic calls if the output is not recognized. It leaves QoS null.
  • rosbags>=0.11.3 is required (0.10 reads a bare .db3 as 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. latched is unchanged.
  • analyze_bag reads per-topic times of an .mcap bag only up to 200 MiB and
    5 s; past either it keeps bag_duration rates and says so in the new
    BagAnalysis.note.
  • The policies_checked entry for History reads "History (risky only, where
    announced)".
  • max_array_length also cuts strings and bytes to that many characters plus
    ...; those cells are listed under _truncated_columns.
  • QosProfile.history is now optional, and a new history_note explains 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 is null; for a Cyclone peer, KEEP_LAST depth 1
    is also null because the binding fills missing QoS with that default. Clients
    that assumed history is always a string must handle null.
  • A discovered endpoint that announced no History keeps its reliability,
    durability and the other policies; before, the whole qos became null.
  • detect_qos_mismatches judges 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_messages with arrays_summary_only shifted 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_messages returned no samples and no explanation when the echo timed
    out (for example a large message with max_array_length null); note now says
    so.
  • list_topics reported 0 publishers and 0 subscribers for a topic missing from
    ros2 topic list -v; it now asks ros2 topic info for that topic.
  • peek_bag_samples converted 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_mismatches treats it as not announced, like the other
    vendors. This path has never run against a real Fast DDS bus.
  • The tests/fixtures/bags bag is left out of the sdist.
  • peek_bag_samples failed on every Humble .db3 bag with "Bag contains no
    type definitions". The reader now gets the type definitions of the distro the
    bag records, or Humble, and note says which. LaserScan.ranges and other
    numeric arrays now come back as lists, not a numpy repr string.
  • analyze_bag rates were count / whole-bag duration, 0.1 to 0.7 percent off on
    periodic topics and meaningless on latched ones (/tf_static showed 0.06 Hz,
    /rosout 0.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_info returned qos_reliability: null on every topic although the
    CLI prints Reliability and Durability per endpoint.
  • peek_dds_samples('/scan') reported the topic as not discovered while
    rt/scan and scan worked; 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 from ros2 topic echo no longer count as data
    columns.
  • ros2 output is decoded as UTF-8 on Windows instead of cp1252.
  • detect_qos_mismatches no longer calls service, action, rosout,
    parameter_events or ros_discovery_info topics typos of each other (for
    example get_parametersRequest vs set_parametersRequest), and no longer
    reports them as orphans. Only plain rt/ 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

Choose a tag to compare

@yaniswav yaniswav released this 02 Oct 12:17

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_mismatches returns a MismatchScan envelope 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 3 lost and 4 discovered events dated by DDS, not by poll time.
  • announced_ns, lost_ns, time_source and related timestamp fields on
    participant_events and list_participants.
  • health_check reports now_ns, tracker status and an observed-domain note.
  • QosProfile gains Liveliness, Ownership, Partition, LatencyBudget,
    DestinationOrder and DataRepresentation.
  • peek_dds_samples on builtin discovery topics returns structured endpoint
    and participant fields instead of a raw repr string.
  • Topic filters accept rt/x and x interchangeably; a filter that matches
    nothing returns the known topics.
  • detect_qos_mismatches also reports matched and not_matched pairs, hints
    (near-miss topic names, path suffixes, type id differences), and the policies
    it did and did not check.

Changed

  • detect_qos_mismatches checks Partition first (with * and ? wildcards),
    then type names, then the RxO rules; Liveliness, LatencyBudget, Ownership,
    DestinationOrder and DataRepresentation join Reliability, Durability and
    Deadline.
  • topic_metrics and peek_dds_samples on 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 None instead 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_ns is 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_endpoints is not
    supported there.
  • DDS Security is not supported, and user-topic payload decoding is disabled.

TopicForge 0.5.4

Choose a tag to compare

@yaniswav yaniswav released this 02 Oct 08:23

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_participants reports the participant name and hostname on Cyclone
    (both were always null).
  • Participant GUIDs were never read, so every participant collapsed onto one
    unknown entry.
  • Vendors were never identified. The vendor id is now read from the GUID prefix;
    Dust DDS and RTI by default still report unknown.
  • The OMG vendor-id table mapped Fast DDS and Cyclone to the wrong ids (now
    01.0F and 01.10). The Fast DDS side is verified statically only.
  • ParticipantInfo.vendor also accepts rti_micro, opensplice, opendds,
    coredx, intercom and dust.
  • detect_qos_mismatches never 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_samples on DCPSPublication / DCPSSubscription listed endpoints
    of participants that had left, and now includes the endpoint type_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

Choose a tag to compare

@yaniswav yaniswav released this 01 Oct 15:59

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]) and dust-dds-python (in [dds-dust]) are not registered, so the documented pip 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_pro plugin 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_check now reports the adapter actually running. It used to say live while serving mock fixtures when ros2 was missing.
  • An explicit TOPICFORGE_DDS_BACKEND is honoured without the ros2 CLI instead of silently serving fixtures.
  • auto no 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_metrics no 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_samples reports 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_metrics states its real limits.

Breaking

  • TOPICFORGE_DDS_BACKEND no longer accepts rti, 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.3

Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#053---2026-10-01

TopicForge 0.5.2

Choose a tag to compare

@yaniswav yaniswav released this 22 Aug 21:04

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 as io.github.yaniswav/topicforge and 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 an mcp-name string 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.2

Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#052---2026-08-22

TopicForge 0.5.1

Choose a tag to compare

@yaniswav yaniswav released this 22 Aug 17:17

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 via pip install topicforge from 2026-07-28 to 2026-08-22: the MCP Python SDK's 2.0.0 release removed the mcp.server.fastmcp module that server/app.py imports, and the dependency was declared as an unbounded mcp>=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 reports frequency_hz_observed = null instead 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).
  • LifecycleBuffer and MetricsBuffer participant/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_iter to non-destructive read_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.md realigned on the shipped 11-tool surface; peek_dds_samples documentation corrected on what the raw decode fallback actually preserves.
pip install topicforge==0.5.1

Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#051---2026-08-22

TopicForge 0.5.0

Choose a tag to compare

@yaniswav yaniswav released this 22 Aug 17:17

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).
  • AdapterError messages 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.0

Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#050---2026-05-21

TopicForge 0.4.0

Choose a tag to compare

@yaniswav yaniswav released this 15 May 20:10

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_samples can 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_samples is called on that topic.
  • analyze_bag enriched 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.0

Full details: https://github.com/yaniswav/TopicForge/blob/main/CHANGELOG.md#040---2026-05-15

TopicForge 0.3.0

Choose a tag to compare

@yaniswav yaniswav released this 14 May 16:32

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

Choose a tag to compare

@yaniswav yaniswav released this 14 May 13:26

TopicForge v0.2.0: safety-first read-only DDS support