Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged autoware_interface_spec_lint at Robotics Stack Exchange
Package Summary
| Version | 1.10.0 |
| License | Apache License 2.0 |
| Build type | AMENT_PYTHON |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/autowarefoundation/autoware_core.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-09-28 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- Yutaka Kondo
Authors
autoware_interface_spec_lint
Config-driven static and manifest checks for the Autoware component interface specifications defined in autoware_component_interface_specs. This package gives fast, pre-build, human-readable diagnostics that complement the compile-time all_specs_valid<> static assertions: it catches “defined-but-unregistered” specs, version inconsistencies, cross-owner shadowing, heavy-raw topics that must not be versioned, and manifest drift that the compiler alone does not.
Each gate’s severity comes from the committed gate config (config/interface_gates.yaml): off (not run), warn (advisory, prints findings but never fails), or error (fails the build when it reports at least one finding). Every implemented gate is set to error, so a finding now fails CI and the pre-commit hook; only the gates listed under “Honest deferrals” below are off. --warn-only overrides every gate to exit 0 for local advisory runs.
Gates
| Gate | Input | Severity | Flags |
|---|---|---|---|
interface_spec_concept |
domain headers | error | a struct with a name[] that is neither a valid topic (Message + depth + reliability + durability) nor a valid service (Service) |
spec_registered |
domain headers | error | a spec struct not listed in its namespace’s using Specs = std::tuple<...> (unless it carries the suppression marker) |
version_consistency |
headers + manifest | error | a domain not declaring exactly one version{...}, or a manifest version that disagrees with the header version |
qos_consistency |
headers + manifest | error | a registered spec whose history / depth / reliability / durability disagrees with its manifest qos block, is missing from the manifest, or names a QoS policy the manifest cannot express |
manifest_fresh |
generator + committed JSON | error | the rebuilt generator output differs from the committed interface_manifest.json (see the binding-gate note below) |
owner_isolation |
manifest(s) | error | a non-base-owner manifest entry whose interface name shadows a base-owner (autowarefoundation) entry |
no_raw_spec_topic |
manifest(s) | error | a versioned topic whose interface name contains a heavy-raw deny substring; services are out of scope |
The manifest audits (owner_isolation, no_raw_spec_topic) take a list of manifest dicts so a future vendor-partition manifest can be cross-checked against the base manifest; with the single committed core manifest owner_isolation is vacuously clean.
Binding manifest-freshness gate
The lint’s manifest_fresh can only bind where the manifest generator binary is available; on a plain checkout / pre-commit run it skips gracefully. The binding freshness gate is the specs-package gtest (autoware_component_interface_specs/test/test_manifest.cpp), which regenerates the manifest with the built generator and asserts byte-equality against the committed interface_manifest.json on every build-and-test CI run. Manifest drift is therefore a hard failure regardless of the advisory lint.
Honest deferrals
The following design gate-table entries are declared off in the committed config and are intentionally deferred; enabling one is rejected by the config loader because there is no implementation to run yet.
| Gate | Why deferred |
|---|---|
no_foreign_if_dependency |
needs per-component provided/required role manifests, which do not exist yet (they arrive with the deploy-time OCI-label manifest track) |
profile_compat |
needs a vendor-specific interface profile that does not exist in this package yet; out of scope for this change |
if_usage_coverage |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
admission_smoke |
runtime gate; needs runtime introspection data this static-analysis package does not have, deferred to future work |
owner_isolation is wired and at error but binds only once a second (vendor-partition) manifest exists to cross-check against. Today the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned, so there is no separate universe-side gate wiring yet.
Suppression contract
A spec struct is exempt from spec_registered when the marker // interface-spec-lint: not-versioned appears on the struct’s own declaration line or on the line directly above it. Use it for a topic that is deliberately not part of the versioned interface set. The marker string is a fixed contract that other packages depend on, so do not change its text.
// interface-spec-lint: not-versioned
struct PointCloudMap {
using Message = sensor_msgs::msg::PointCloud2;
static constexpr char name[] = "/map/point_cloud_map";
// ...
};
Usage
# Lint the core specs with the committed gate config (severities from the config).
ament_autoware_interface_spec_lint
# Advisory local run: print findings but always exit 0.
ament_autoware_interface_spec_lint --warn-only
# Explicit paths and an alternate gate config.
ament_autoware_interface_spec_lint \
--config common/autoware_interface_spec_lint/config/interface_gates.yaml \
--spec-dir common/autoware_component_interface_specs/include/autoware/component_interface_specs \
--manifest common/autoware_component_interface_specs/interface_manifest.json
manifest_fresh
manifest_fresh needs the manifest generator binary. Point at it with --generator <path> or the INTERFACE_MANIFEST_GENERATOR environment variable. When neither is available the check skips gracefully (the binding gate is the specs-package gtest).
export INTERFACE_MANIFEST_GENERATOR=$PWD/build/autoware_component_interface_specs/generate_interface_manifest
ament_autoware_interface_spec_lint \
--manifest common/autoware_component_interface_specs/interface_manifest.json \
--generator "$INTERFACE_MANIFEST_GENERATOR"
Gate config
config/interface_gates.yaml maps each gate to a severity and carries the no_raw_spec_topic deny/allow lists and the owner_isolation base owner. The loader rejects an unknown gate name and rejects enabling a deferred gate (it may only be declared off).
Changelog for package autoware_interface_spec_lint
1.10.0 (2026-09-28)
-
Merge remote-tracking branch 'origin/main' into tmp/bot/bump_version_base
-
feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits (#1315)
* feat(autoware_interface_spec_lint): ratchet interface gates to error and add manifest audits Take the WARN-only lint landed earlier and give it teeth at the CI boundary: findings now fail the build instead of only being printed. Severity mechanism:
- Add a Severity enum (off/warn/error) and exit_code_for(): a gate fails only at error severity with at least one finding.
- Add a committed gate config (config/interface_gates.yaml) mapping each gate to a severity, loaded via --config with a packaged default path. The loader rejects unknown gate names and rejects enabling a deferred gate. --warn-only remains as an explicit local/advisory override. New manifest audits (adapted to the committed schema; multi-manifest capable so a future vendor-partition manifest can be cross-checked):
- owner_isolation(manifests, base_owner): a non-base-owner entry whose interface name shadows a base-owner entry is a finding (vacuously clean on the single core manifest).
- no_raw_spec_topic(manifests, deny, allow): a versioned topic whose name contains a heavy-raw deny substring is a finding; request/response services are out of scope (the sanctioned differential-map query service is not flagged), and the derived grid obstacle_grid does not match. Ratchet:
- interface_spec_concept, spec_registered, version_consistency, qos_consistency, manifest_fresh, owner_isolation and no_raw_spec_topic are set to error.
- The pre-commit hook drops --warn-only, so a finding now fails it. no_raw_spec_topic's heavy-raw deny list still lists the retired point_cloud_map topic name; the committed manifest no longer carries that entry, so the check reports no findings for it. manifest_fresh stays advisory locally (skips without a generator) and leans on the specs package's own committed-manifest gtest and CMake compile definition -- both already in place on this branch's base -- for the hard drift gate in build-and-test CI. Honest deferrals: no_foreign_if_dependency / profile_compat (need per-component role manifests / a vendor-specific interface profile that does not exist yet) and the runtime gates if_usage_coverage / admission_smoke (need runtime introspection data this static-analysis package does not have) are kept off with documented reasons. No universe-side gate wiring yet: the universe versioned surface is exactly the core re-exports (single version authority in core) and universe-owned specs are unversioned until a future vendor-partition manifest lands.
* fix(autoware_interface_spec_lint): drop the 0.x-only major-version policy version_consistency runs at error severity once the gates ratchet, so the hard-coded 'MAJOR must be 0' finding would fail CI on the first legitimate MAJOR bump by construction. Keep the load-bearing half of the check (header-vs-manifest version agreement) and leave bump discipline to review.
* fix(autoware_interface_spec_lint): reject empty gate configs and cover run()'s exit code An empty (or absent) [gates:]{.title-ref} key loaded successfully with every gate defaulting to off, so the lint would report zero findings and exit 0 against any tree regardless of its actual state. load_config() now raises ValueError when the parsed severities map is empty, matching the fail-closed contract the loader already applies to unknown gate names and deferred-gate misuse. test_config.py also pins qos_consistency into the set of gates the committed config ratchets to error severity; the existing assertion listed every implemented gate except that one. No prior test drove run() itself over a violating tree with an error-severity gate enabled: test_severity.py covers exit_code_for in isolation, and test_acceptance.py only pins the converse (a clean tree exits 0). Add test_run_exit_code.py to close that gap and assert run() returns 1 on an error-severity finding, stays at 0 under warn_only, and stays at 0 when the only finding is warn severity.
* test(autoware_interface_spec_lint): drop the duplicate out-of-scope service test test_differential_pcd_map_service_stays_out_of_scope fed the identical manifest entry to the identical call and asserted the identical result as test_service_with_denied_substring_is_out_of_scope, so it added no coverage. Its comment also misdescribed what it guarded: the deny entry it was added alongside, "point_cloud_map", is not a substring of /map/get_differential_pointcloud_map at all -- the pre-existing "pointcloud_map" entry is the one that matches. Since no_raw_spec_topic scopes on kind == "topic" and never on the name, one service case covers every deny spelling, so fold that reasoning into the surviving test's comment. Addresses a review comment on #1315. ---------
File truncated at 100 lines see the full file