Skip to content

Release 0.7.0: changelogs, version bump, and two record-keeping fixes - #644

Open
bburda wants to merge 7 commits into
mainfrom
release/0.7.0
Open

Release 0.7.0: changelogs, version bump, and two record-keeping fixes#644
bburda wants to merge 7 commits into
mainfrom
release/0.7.0

Conversation

@bburda

@bburda bburda commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Pull Request

Summary

Prepares the 0.7.0 release: every package changelog gains its 0.7.0 section, the version is
bumped across the tree, and two record-keeping defects found while writing it are fixed.

Changelogs. The 0.7.0 (2026-08-27) section is filled for all 19 packages from the 459
commits since bdcc4ed0 (the 0.6.0 release commit). Thirteen packages had no entry at all. Four
carried a Forthcoming section; those bullets are kept and moved under the released heading.

ros2_medkit_graph_watchdog gains its first changelog and the include that puts it on the
aggregated docs page, so all 19 packages are covered there rather than 18. Its package.xml
description listed seven silent-fault classes; five detectors are registered (qos_mismatch,
orphan, node_death, param_drift, lifecycle_expectation) and the description now names
those. GRAPH_TF_STALE and GRAPH_LATENCY_BUDGET keep their reserved codes and are described as
undelivered, matching what the package README already said.

ros2_medkit_fault_detection dated its initial release 0.6.0 — a release it was not part
of, as the 16 packages released at 0.6.0-1 confirm. The section moves to 0.7.0.

release.sh matched docs/conf.py with a double-quoted pattern while the file uses single
quotes, so bump silently skipped it and verify reported the file as unknown on every run.
Both legs now accept either quote style.

The 0.6.0 changelog of ros2_medkit_fault_manager gains the entry it never got: that release
moved the default rosbag storage format back from mcap to sqlite3. The 0.4.0 entries are
accurate for the release they sit under — the default was mcap in 0.4.0 and 0.5.0 — and are
left alone.

Breaking changes called out in the 0.7.0 notes

  • The default rosbag storage format is mcap again. Recordings land as .mcap instead of
    .db3, and the bulk-data download filename changes with them. snapshots.rosbag.format: sqlite3 keeps the previous on-disk format.
  • x-medkit-graph is at schema_version "2.0.0". The error_reason values node_offline,
    topic_stale and no_data_source are gone; metrics_stale is the only reachable value.
  • An action execution now belongs to the entity it was started on. An execution id no longer
    works as a global handle, and reaching one through another entity answers 404.
  • GET <entity-path>/docs is readable by viewer rather than admin, because the permission
    table is now derived from the route registrations instead of a hand-maintained literal.
  • The lifecycle status operationId values were singularized - getAppStatus and
    putAppStatusRestart rather than the plural collection forms they were built from before -
    which renames the matching methods in a generated client.

Review

Five lenses (three Codex, two Claude) read the changelogs against the code before this was
marked ready. They found the lifecycle operationId entry stating its migration backwards, a
fault code in the graph watchdog entry that exists nowhere in the tree, a detector described so
broadly it would appear to fire on every graph, three packages claiming a DDS domain their tests
are opted out of, four operator-visible features with no entry at all, one misattributed pull
request, four entries citing the issue rather than the pull request that delivered the work, and
two unanchored version patterns in release.sh. All are fixed in the second commit; the
findings and their evidence are in the commit message.


Issue


Type

  • Bug fix
  • New feature or tests
  • Breaking change
  • Documentation only

Testing

  • sphinx-build -W --keep-going -b html docs is clean. The only remaining warnings are
    doxygenclass / doxygenstruct reporting a missing docs/_build/doxygen/xml/index.xml, which
    is generated by the Generate Doxygen XML step in docs.yml before Sphinx runs.
  • All 19 packages carry a 0.7.0 section, no Forthcoming section remains, and
    docs/changelog.rst has 19 include:: directives for 19 packages.
  • ./scripts/release.sh verify 0.7.0 reports all versions consistent.
  • The conf.py fix is checked by reverting that file to 0.6.0 and re-running bump: the
    patched script rewrites it, while the previous one reports unknown -> 0.7.0 and leaves the
    file at 0.6.0.
  • scripts/generate_verification.py flips seven Scripts requirements to verified, matching
    tests that already carry their @verifies tags.

Checklist

  • Breaking changes are clearly described (and announced in docs / changelog if needed)
  • Tests were added or updated if needed
  • Docs were updated if behavior or public API changed

@bburda bburda self-assigned this Aug 28, 2026
bburda added 6 commits August 28, 2026 21:05
Fill the 0.7.0 section of every package changelog from the 459 commits since
0.6.0. Thirteen packages had no entry at all; four carried a Forthcoming
section whose bullets are kept and moved under the released heading.

ros2_medkit_graph_watchdog gains its first changelog and the include that
puts it in the aggregated docs page, so all nineteen packages are now
covered there.

ros2_medkit_fault_detection dated its initial release 0.6.0, a release it
was never part of. The section moves to 0.7.0.

Three entries are operator-visible and called out as breaking: the default
rosbag storage format is mcap again, so recordings land as .mcap and the
bulk-data download filename changes with them; the x-medkit-graph health
model is at schema_version 2.0.0 with three error_reason values gone; and
the lifecycle status operationId values were pluralized, which renames the
matching methods in a generated client.

The graph watchdog package description listed seven silent-fault classes.
Five detectors are registered - qos_mismatch, orphan, node_death,
param_drift and lifecycle_expectation - and the description now names
those. GRAPH_TF_STALE and GRAPH_LATENCY_BUDGET keep their reserved codes
and are described as undelivered in the changelog, as the package README
already described them.

Running the verification generator flips seven Scripts requirements to
verified, matching the tests that already carry their @verifies tags.
release.sh matched docs/conf.py with a double-quoted pattern while the file
uses single quotes, so bump silently left it behind and verify reported the
file as 'unknown' on every run. Both legs now accept either quote style.
Checked by reverting conf.py to 0.6.0 and re-running bump: the patched
script rewrites it, the previous one reports 'unknown -> 0.7.0' and leaves
the file at 0.6.0.

The 0.6.0 changelog of ros2_medkit_fault_manager gains the entry it never
got: that release moved the default rosbag storage format back from mcap to
sqlite3. The 0.4.0 entries in the gateway and fault_manager changelogs are
accurate for the release they sit under - the default was mcap in 0.4.0 and
0.5.0 - and are left alone.

All 19 package.xml, version.hpp, docs/conf.py, docs/pyproject.toml,
docs/Doxyfile, QUALITY_DECLARATION.md and the REST examples read 0.7.0;
'release.sh verify 0.7.0' reports all versions consistent.
Five lenses read the changelogs against the code. What they found:

The lifecycle operationId entry stated the migration backwards. #497 moved
generation from the plural collection name to the singular entity name, so a
client gets getAppStatus, not getAppsStatus. This was the one entry marked
breaking, which is the one a client maintainer reads.

The graph watchdog entry named a fault code that does not exist. node_death
is the detector id; the code on the wire is GRAPH_NODE_DISAPPEARED. The
GRAPH_ namespace is a frozen external contract, so a filter written from the
release notes would have matched nothing. The same entry documented one code
for lifecycle_expectation, which raises three - GRAPH_NODE_UNREADABLE and
GRAPH_NODE_NOT_MANAGED cover the cases where the state could not be read at
all, and a consumer filtering on GRAPH_NODE_INACTIVE sees neither.

The orphan entry described a detector that would fire on nearly every graph.
One-sidedness only admits a topic; the fault needs a complementary near-miss
counterpart, which is what makes it the signature of a name typo.

Freeze-frame is scoped to plugin-backed entities and needs a loaded plugin;
the entry claimed it unconditionally. Three packages claimed their tests take
a DDS domain when those tests are opted out of allocation entirely.

Four operator-visible features had no entry at all: the fault-trigger
threshold engine and its three routes, aggregation.peer_auth_header with the
redaction that keeps it out of the configurations API, the secure field
profile, and auto_cleared_codes on the SSE wire.

Attribution: the Humble fallback warning belongs to #622, not #636. Four
entries cited the issue that asked for the work rather than the pull request
that delivered it. Two graph_provider entries duplicated two others.

release.sh: the conf.py version pattern was unanchored, so 0.7.0-dev and
0.7.0.1 both read as 0.7.0 and passed verify, and release was rewritten but
never checked. Both are now read through one helper that anchors the value to
its closing quote and accepts any spacing, bump confirms its own rewrite
instead of trusting sed's exit code, and verify compares release against
version. Checked against 0.7.0-dev, 0.7.0.1 and a release that disagrees with
version: all three now report a mismatch.
The routes exist on Apps only - there is no component path - and the engine
is gated on a loaded plugin as well as on fault_triggers.enabled, so the
default of true is necessary rather than sufficient. The poll interval is
floored at 50 ms and a lower value is reported.
On a forward it is the fallback: with forward_auth enabled and a caller
credential present, the caller's token wins, so the peer keeps being told the
end user. The entry claimed the gateway credential unconditionally.
They have since 0.3.0, and the README already tells the reader to apt install
the gateway. The page now leads with the apt path and names the three packages
that genuinely are not in the index: opcua, graph_watchdog and fault_detection.
The release branch was cut before that work merged, so the largest change in
0.7.0 had no entry at all.

Two items are breaking for a caller. An action execution now belongs to the
entity it was started on, so an execution id no longer works as a global
handle and reaching one through another entity answers 404. And GET on a
scoped docs path is readable by viewer rather than admin, because the
permission table is now derived from the route registrations rather than kept
as a literal beside them.

The rest is what the derivation buys and what changed on the wire beside it:
corrected statuses on four paths, a Location that is sent and dereferenceable,
new advertised URIs on entity detail, two added operation ids with none
renamed and no route added or removed, and a status recorder whose sweep is
driven from the served document rather than a list.

The fault manager accepts the fault_code length it advertises, and a long code
keeps its recording instead of losing it to a filename limit.

Deliberately not claimed: that the document now matches everything the gateway
honours. Over-declaration is not falsified by a run, request bodies are
validated against no declared schema, and statuses answered before routing are
invisible to the recorder. The stranded-body case from the issue is signalled
with a header, not fixed.
@bburda
bburda marked this pull request as ready for review August 31, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Release v0.7.0

1 participant