Skip to main content
Glama

health_check

Read-onlyIdempotent

Report TopicForge environment state instantly to diagnose ROS2/DDS setup issues: mode, backends, ROS tools, distro, domain, and tracker status. Read-only, never blocks, always succeeds.

Instructions

Report TopicForge environment state as a HealthReport: mode, ros_backend, dds_backend, ros_tools_available, ros2_distro, rmw_implementation, dds_domain_id and observed_domain_note (only the domain joined at startup is observed), server version and sample cap; for a live DDS backend also observer_started_ns / now_ns (nothing earlier was watched) and the discovery tracker status tracker_* (errors, evictions or a stale pass mean gaps). live with ros_backend none is a DDS-only setup: use list_endpoints. With dds_backend none, dds_inactive_note says why. payload_decoding is disabled (DDS user-topic payloads are not decoded); dds_security is not_supported. Always succeeds: call it first when something looks wrong. Read-only; no side effects. Duration: never waits for a lock and never runs the ros2 CLI; it answers at once.

Input Schema

NameRequiredDescriptionDefault

No arguments

Output Schema

NameRequiredDescriptionDefault
modeYesMode serving: `mock` or `live` (`live` with `ros_backend` `none`: DDS tools only); may differ from `requested_mode` after a fallback.
noteNoOne sentence of context, or `None`.
now_nsNoServer wall-clock time (ns since epoch) when this report was built.
rmw_sourceNo`env`, `ros2_cli`, `distro_default` (not verified on the graph) or `none`.
dds_backendNoDDS backend serving: `mock`, `cyclone`, `fast`, or `none` (DDS module inactive).
ros2_distroNo`ROS_DISTRO` if set (disclosed by design under the local-trust model).
ros_backendNoROS 2 backend: `ros2_cli`, `mock` or `none`.
dds_securityNoDDS Security is not handled: protected endpoints and data are invisible.
dds_domain_idNoDDS domain id observed when the DDS module is active.
requested_modeYesMode requested by configuration (may be `auto`).
ros2_availableYesWhether a `ros2` CLI is on PATH.
server_versionYesTopicForge version.
tracker_errorsNoTracker passes that raised; non-zero means gaps.
tracker_passesNoCompleted discovery tracker passes since start.
tracker_runningNoWhether the discovery tracker thread is alive (Cyclone); `None` without a tracker.
contract_versionNoOutput contract version; changes when a field is renamed, removed or retyped.
max_sample_countYesServer cap on samples per call; larger requests are clamped.
payload_decodingNo`disabled`: DDS user-topic payloads are not decoded.
dds_inactive_noteNoWhy `dds_backend` is `none` while ROS 2 serves; else `null`.
ros_security_noteNoSet when `ros_security_enabled`: what stays invisible.
rmw_implementationNoROS 2 middleware, e.g. `rmw_fastrtps_cpp`; `None` when `rmw_source` is `none`.
observer_started_nsNons when the DDS observer joined; nothing earlier was watched. `None` without one.
ros_tools_availableNoTrue when the ROS 2 tools can run (`ros_backend` is not `none`); on a DDS-only setup use `list_endpoints`.
sim_clock_publishedNoWhether `/clock` had a publisher at the last graph read (stamps may be sim time); `None` in mock or without a recent read.
middleware_availableNoTrue when a DDS backend serves; else whether the configured binding is importable.
observed_domain_noteNoWhich DDS domain is observed: only the one joined at startup; others are invisible.
ros_security_enabledNo`ROS_SECURITY_ENABLE` is `true`; `None` unless the ros2 CLI serves.
tracker_last_pass_nsNons of the last tracker pass; far older than `now_ns` means stale lifecycle.
payload_decoding_noteNoReason for `payload_decoding`.
ros_security_strategyNo`ROS_SECURITY_STRATEGY` when set to a valid value.
tracker_cache_evictionsNoDiscovery entries dropped from a full tracker cache; non-zero means the bus is bigger than listed.
ros_security_keystore_setNoWhether a keystore variable is set (the path is never shown).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed70 schema fields changedv0.8.0
    • removedOutput schema / properties / contract_version / default
      Removed value: -2
    • changedOutput schema / properties / contract_version / description
      Previous value: -"Output contract version; changes only when a field is renamed, removed or retyped."New value: +"Output contract version; changes when a field is renamed, removed or retyped."
    • removedOutput schema / properties / dds_backend / default
      Removed value: -"none"
    • removedOutput schema / properties / dds_domain_id / anyOf
      Removed value: -[
      -  {
      -    "maximum": 232,
      -    "minimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / dds_domain_id / default
      Removed value: -null
    • addedOutput schema / properties / dds_domain_id / maximum
      Added value: +232
    • addedOutput schema / properties / dds_domain_id / minimum
      Added value: +0
    • addedOutput schema / properties / dds_domain_id / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedOutput schema / properties / dds_inactive_note / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / dds_inactive_note / default
      Removed value: -null
    • changedOutput schema / properties / dds_inactive_note / description
      Previous value: -"Why `dds_backend` is `none` while ROS 2 serves (not selected, binding missing, or failed to start); else `null`."New value: +"Why `dds_backend` is `none` while ROS 2 serves; else `null`."
    • addedOutput schema / properties / dds_inactive_note / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / dds_security / default
      Removed value: -"not_supported"
    • removedOutput schema / properties / middleware_available / default
      Removed value: -false
    • changedOutput schema / properties / mode / description
      Previous value: -"Mode actually serving: `mock` or `live` (`live` with `ros_backend` `none`: DDS tools only). May differ from `requested_mode` after a fallback."New value: +"Mode serving: `mock` or `live` (`live` with `ros_backend` `none`: DDS tools only); may differ from `requested_mode` after a fallback."
    • removedOutput schema / properties / note / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / note / default
      Removed value: -null
    • addedOutput schema / properties / note / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / now_ns / anyOf
      Removed value: -[
      -  {
      -    "minimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / now_ns / default
      Removed value: -null
    • addedOutput schema / properties / now_ns / minimum
      Added value: +0
    • addedOutput schema / properties / now_ns / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedOutput schema / properties / observed_domain_note / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / observed_domain_note / default
      Removed value: -null
    • addedOutput schema / properties / observed_domain_note / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / observer_started_ns / anyOf
      Removed value: -[
      -  {
      -    "minimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / observer_started_ns / default
      Removed value: -null
    • addedOutput schema / properties / observer_started_ns / minimum
      Added value: +0
    • addedOutput schema / properties / observer_started_ns / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedOutput schema / properties / payload_decoding / default
      Removed value: -"disabled"
    • removedOutput schema / properties / payload_decoding_note / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / payload_decoding_note / default
      Removed value: -"user-topic payload decoding is switched off until it is validated on a real bus; builtin discovery topics are still readable"
    • addedOutput schema / properties / payload_decoding_note / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / rmw_implementation / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / rmw_implementation / default
      Removed value: -null
    • addedOutput schema / properties / rmw_implementation / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / rmw_source / default
      Removed value: -"none"
    • removedOutput schema / properties / ros2_distro / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / ros2_distro / default
      Removed value: -null
    • addedOutput schema / properties / ros2_distro / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / ros_backend / default
      Removed value: -"none"
    • addedOutput schema / properties / ros_security_enabled
      Added value: +{
      +  "description": "`ROS_SECURITY_ENABLE` is `true`; `None` unless the ros2 CLI serves.",
      +  "type": [
      +    "boolean",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / ros_security_keystore_set
      Added value: +{
      +  "description": "Whether a keystore variable is set (the path is never shown).",
      +  "type": [
      +    "boolean",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / ros_security_note
      Added value: +{
      +  "description": "Set when `ros_security_enabled`: what stays invisible.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / ros_security_strategy
      Added value: +{
      +  "description": "`ROS_SECURITY_STRATEGY` when set to a valid value.",
      +  "enum": [
      +    "Enforce",
      +    "Permissive",
      +    null
      +  ],
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • removedOutput schema / properties / ros_tools_available / default
      Removed value: -false
    • removedOutput schema / properties / sim_clock_published / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / sim_clock_published / default
      Removed value: -null
    • changedOutput schema / properties / sim_clock_published / description
      Previous value: -"Whether `/clock` had a publisher in the last graph read (a hint that stamps may be sim time). `None` in mock or without a recent read; `health_check` never runs `ros2`."New value: +"Whether `/clock` had a publisher at the last graph read (stamps may be sim time); `None` in mock or without a recent read."
    • addedOutput schema / properties / sim_clock_published / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
    • removedOutput schema / properties / tracker_cache_evictions / anyOf
      Removed value: -[
      -  {
      -    "minimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / tracker_cache_evictions / default
      Removed value: -null
    • changedOutput schema / properties / tracker_cache_evictions / description
      Previous value: -"Discovery entries dropped from a full tracker cache (4096 each); non-zero means the bus is bigger than listed."New value: +"Discovery entries dropped from a full tracker cache; non-zero means the bus is bigger than listed."
    • addedOutput schema / properties / tracker_cache_evictions / minimum
      Added value: +0
    • addedOutput schema / properties / tracker_cache_evictions / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedOutput schema / properties / tracker_errors / anyOf
      Removed value: -[
      -  {
      -    "minimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / tracker_errors / default
      Removed value: -null
    • addedOutput schema / properties / tracker_errors / minimum
      Added value: +0
    • addedOutput schema / properties / tracker_errors / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedOutput schema / properties / tracker_last_pass_ns / anyOf
      Removed value: -[
      -  {
      -    "minimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / tracker_last_pass_ns / default
      Removed value: -null
    • addedOutput schema / properties / tracker_last_pass_ns / minimum
      Added value: +0
    • addedOutput schema / properties / tracker_last_pass_ns / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedOutput schema / properties / tracker_passes / anyOf
      Removed value: -[
      -  {
      -    "minimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / tracker_passes / default
      Removed value: -null
    • addedOutput schema / properties / tracker_passes / minimum
      Added value: +0
    • addedOutput schema / properties / tracker_passes / type
      Added value: +[
      +  "integer",
      +  "null"
      +]
    • removedOutput schema / properties / tracker_running / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / tracker_running / default
      Removed value: -null
    • addedOutput schema / properties / tracker_running / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
  2. Changed50 schema fields changedv0.7.1
    • removedInput schema / title
      Removed value: -"health_checkArguments"
    • addedOutput schema / properties / contract_version
      Added value: +{
      +  "default": 2,
      +  "description": "Output contract version; changes only when a field is renamed, removed or retyped.",
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / dds_backend / description
      Previous value: -"DDS backend of the adapter actually serving requests. `none` when the DDS module is not active (default for ROS2-only installs). `mock` for synthetic fixtures. `cyclone` requires `pip install \"topicforge[dds-cyclone]\"` (Eclipse CycloneDDS); `fast` requires a Fast DDS Python binding built from eProsima sources (not on PyPI); `opendds` and `dust` are permanent stub adapters that never serve."New value: +"DDS backend serving: `mock`, `cyclone`, `fast`, or `none` (DDS module inactive)."
    • changedOutput schema / properties / dds_backend / enum
      Previous value: -[
      -  "mock",
      -  "cyclone",
      -  "fast",
      -  "opendds",
      -  "dust",
      -  "none"
      -]New value: +[
      +  "mock",
      +  "cyclone",
      +  "fast",
      +  "none"
      +]
    • removedOutput schema / properties / dds_backend / title
      Removed value: -"Dds Backend"
    • removedOutput schema / properties / dds_domain_id / title
      Removed value: -"Dds Domain Id"
    • addedOutput schema / properties / dds_inactive_note
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Why `dds_backend` is `none` while ROS 2 serves (not selected, binding missing, or failed to start); else `null`."
      +}
    • removedOutput schema / properties / dds_inactive_reason
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Why `dds_backend` is `none` while the ROS 2 CLI serves: the backend was not selected (`TOPICFORGE_DDS_BACKEND` unset or `mock`), its Python binding is not installed, or the binding is installed but the adapter failed to start. `null` when a DDS backend is serving or the cause is not known.",
      -  "title": "Dds Inactive Reason"
      -}
    • changedOutput schema / properties / dds_security / description
      Previous value: -"DDS Security is not handled. On a secured domain TopicForge can show participants but not protected endpoints or data."New value: +"DDS Security is not handled: protected endpoints and data are invisible."
    • removedOutput schema / properties / dds_security / title
      Removed value: -"Dds Security"
    • changedOutput schema / properties / max_sample_count / description
      Previous value: -"Server-side cap on the number of samples returned per `sample_messages` call. Requests above this limit are silently clamped; the value is exposed here so a client can size its requests proactively. Constant within a given server version."New value: +"Server cap on samples per call; larger requests are clamped."
    • removedOutput schema / properties / max_sample_count / title
      Removed value: -"Max Sample Count"
    • changedOutput schema / properties / middleware_available / description
      Previous value: -"True when a DDS backend is serving (`dds_backend` is not `none`). When the DDS module is inactive (`dds_backend == 'none'`), whether the *configured* backend's Python bindings are importable, so a missing binding is visible."New value: +"True when a DDS backend serves; else whether the configured binding is importable."
    • removedOutput schema / properties / middleware_available / title
      Removed value: -"Middleware Available"
    • changedOutput schema / properties / mode / description
      Previous value: -"Runtime mode of the adapter actually serving requests: `mock` or `live`. `live` with `ros_backend` `none` means the DDS tools are live and the ROS 2 tools are not available. Can differ from `requested_mode` when a live backend could not start (e.g. `live` requested without `ros2` installed falls back to `mock`)."New value: +"Mode actually serving: `mock` or `live` (`live` with `ros_backend` `none`: DDS tools only). May differ from `requested_mode` after a fallback."
    • removedOutput schema / properties / mode / title
      Removed value: -"Mode"
    • addedOutput schema / properties / note
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "One sentence of context, or `None`."
      +}
    • removedOutput schema / properties / now_ns / title
      Removed value: -"Now Ns"
    • changedOutput schema / properties / observed_domain_note / description
      Previous value: -"Plain statement of which DDS domain is observed, set when a DDS module is active: only the domain joined at startup is visible, a program on another domain is invisible."New value: +"Which DDS domain is observed: only the one joined at startup; others are invisible."
    • removedOutput schema / properties / observed_domain_note / title
      Removed value: -"Observed Domain Note"
    • changedOutput schema / properties / observer_started_ns / description
      Previous value: -"Wall-clock time (ns since epoch) when the DDS observer joined the bus. Nothing earlier than this was watched: `now_ns` minus this is how long TopicForge has been observing. `None` without a live DDS observer."New value: +"ns when the DDS observer joined; nothing earlier was watched. `None` without one."
    • removedOutput schema / properties / observer_started_ns / title
      Removed value: -"Observer Started Ns"
    • changedOutput schema / properties / payload_decoding / description
      Previous value: -"Whether DDS user-topic payloads are decoded. `disabled` today: `peek_dds_samples` and `topic_metrics` do not return message content for user topics."New value: +"`disabled`: DDS user-topic payloads are not decoded."
    • removedOutput schema / properties / payload_decoding / title
      Removed value: -"Payload Decoding"
    • addedOutput schema / properties / payload_decoding_note
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": "user-topic payload decoding is switched off until it is validated on a real bus; builtin discovery topics are still readable",
      +  "description": "Reason for `payload_decoding`."
      +}
    • removedOutput schema / properties / payload_decoding_reason
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": "user-topic payload decoding is switched off until it is validated on a real bus; builtin discovery topics are still readable",
      -  "description": "One-line reason for `payload_decoding`.",
      -  "title": "Payload Decoding Reason"
      -}
    • changedOutput schema / properties / requested_mode / description
      Previous value: -"Mode requested via configuration (may be `auto`)."New value: +"Mode requested by configuration (may be `auto`)."
    • removedOutput schema / properties / requested_mode / title
      Removed value: -"Requested Mode"
    • addedOutput schema / properties / rmw_implementation
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "ROS 2 middleware, e.g. `rmw_fastrtps_cpp`; `None` when `rmw_source` is `none`."
      +}
    • addedOutput schema / properties / rmw_source
      Added value: +{
      +  "default": "none",
      +  "description": "`env`, `ros2_cli`, `distro_default` (not verified on the graph) or `none`.",
      +  "enum": [
      +    "env",
      +    "ros2_cli",
      +    "distro_default",
      +    "none"
      +  ],
      +  "type": "string"
      +}
    • removedOutput schema / properties / ros2_available / title
      Removed value: -"Ros2 Available"
    • changedOutput schema / properties / ros2_distro / description
      Previous value: -"Value of `ROS_DISTRO` if set in the environment. **Env disclosure, by design**: under the local-trust threat model (see README 'Security model'), the MCP client is a trusted agent on a machine the user controls, and exposing the ROS2 distro lets it adapt to e.g. `humble`/`jazzy` differences. For a hosted multi-tenant TopicForge endpoint this field would be scrubbed ."New value: +"`ROS_DISTRO` if set (disclosed by design under the local-trust model)."
    • removedOutput schema / properties / ros2_distro / title
      Removed value: -"Ros2 Distro"
    • changedOutput schema / properties / ros_backend / description
      Previous value: -"Active ROS2 backend. `ros2_cli` when the `ros2` CLI is on PATH and live mode resolves to a Ros2CliAdapter (alone or as the ROS half of a composite). `mock` when MockAdapter serves the ROS surface. `none` when no ROS2 backend is active (e.g. DDS-only live install with no `ros2` CLI). Together with `dds_backend` it tells the ROS2 and DDS halves of the runtime apart."New value: +"ROS 2 backend: `ros2_cli`, `mock` or `none`."
    • removedOutput schema / properties / ros_backend / title
      Removed value: -"Ros Backend"
    • changedOutput schema / properties / ros_tools_available / description
      Previous value: -"True when the ROS 2 tools (`list_topics`, `get_topic_info`, `sample_messages`, `analyze_bag`, `peek_bag_samples`) can run, i.e. `ros_backend` is not `none`. False on a DDS-only setup: use `list_endpoints` for topics and wiring there."New value: +"True when the ROS 2 tools can run (`ros_backend` is not `none`); on a DDS-only setup use `list_endpoints`."
    • removedOutput schema / properties / ros_tools_available / title
      Removed value: -"Ros Tools Available"
    • changedOutput schema / properties / server_version / description
      Previous value: -"TopicForge server version (matches the PyPI release of the `topicforge` package)."New value: +"TopicForge version."
    • removedOutput schema / properties / server_version / title
      Removed value: -"Server Version"
    • changedOutput schema / properties / sim_clock_published / description
      Previous value: -"Whether `/clock` has at least one publisher on the ROS 2 graph. True suggests nodes may run on simulated time (`use_sim_time`), so `header.stamp` values are sim time, not wall time (compare with `received_ns`). It is a hint: a publisher on `/clock` does not prove a given node follows it. `None` in mock mode or when the `ros2` CLI could not answer."New value: +"Whether `/clock` had a publisher in the last graph read (a hint that stamps may be sim time). `None` in mock or without a recent read; `health_check` never runs `ros2`."
    • removedOutput schema / properties / sim_clock_published / title
      Removed value: -"Sim Clock Published"
    • changedOutput schema / properties / tracker_cache_evictions / description
      Previous value: -"Discovery entries dropped because a tracker cache was full (4096 per cache). Non-zero means the bus is bigger than what is listed."New value: +"Discovery entries dropped from a full tracker cache (4096 each); non-zero means the bus is bigger than listed."
    • removedOutput schema / properties / tracker_cache_evictions / title
      Removed value: -"Tracker Cache Evictions"
    • changedOutput schema / properties / tracker_errors / description
      Previous value: -"Discovery tracker passes that raised (swallowed and logged). Non-zero means gaps."New value: +"Tracker passes that raised; non-zero means gaps."
    • removedOutput schema / properties / tracker_errors / title
      Removed value: -"Tracker Errors"
    • changedOutput schema / properties / tracker_last_pass_ns / description
      Previous value: -"Wall-clock time (ns since epoch) of the last completed tracker pass. A value far older than `now_ns` means lifecycle is stale."New value: +"ns of the last tracker pass; far older than `now_ns` means stale lifecycle."
    • removedOutput schema / properties / tracker_last_pass_ns / title
      Removed value: -"Tracker Last Pass Ns"
    • removedOutput schema / properties / tracker_passes / title
      Removed value: -"Tracker Passes"
    • changedOutput schema / properties / tracker_running / description
      Previous value: -"Whether the continuous discovery tracker thread is alive (Cyclone). `None` when the backend has no tracker."New value: +"Whether the discovery tracker thread is alive (Cyclone); `None` without a tracker."
    • removedOutput schema / properties / tracker_running / title
      Removed value: -"Tracker Running"
  3. Changed1 schema field changedv0.6.3
    • addedOutput schema / properties / sim_clock_published
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "boolean"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Whether `/clock` has at least one publisher on the ROS 2 graph. True suggests nodes may run on simulated time (`use_sim_time`), so `header.stamp` values are sim time, not wall time (compare with `received_ns`). It is a hint: a publisher on `/clock` does not prove a given node follows it. `None` in mock mode or when the `ros2` CLI could not answer.",
      +  "title": "Sim Clock Published"
      +}
  4. First observedv0.5.6

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish read-only, idempotent, non-destructive behavior, and the description adds substantial context beyond that: it always succeeds, never waits for a lock, never runs the ros2 CLI, and answers at once. It also discloses field-level semantics such as observed_domain_note only reflecting the startup domain and tracker_* errors indicating gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is a single front-loaded paragraph with no filler, and the dense field list earns its space by attaching operational meaning to fields like observed_domain_note and tracker_*. The critical advice to call it first is stated clearly at the end.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description does not need to explain return values, but it still adds the failure-mode and field-semantics context an agent needs to interpret the report. It covers the always-succeeds guarantee, DDS-only and no-DDS cases, and the limited payload decoding and security scope.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the baseline is 4 and there is no input schema detail the description needs to compensate for. The description appropriately focuses on the report and its semantics rather than inventing parameter guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: report TopicForge environment state as a HealthReport. It distinguishes the tool from siblings by naming list_endpoints for DDS-only setups and by explaining how health_check differs from a live data-listing/query tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage guidance: call it first when something looks wrong. It also names the relevant alternative, list_endpoints, for the specific case where ros_backend is none, and explains what dds_inactive_note means when dds_backend is none.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.