From 5fd6b4abaa922682ddc989b674b3b836176c2f8c Mon Sep 17 00:00:00 2001 From: Jan Ehrensperger Date: Thu, 15 Oct 2026 06:17:15 +0200 Subject: [PATCH] [Bug Fix] component() rejects assumed_system_requirements in reqs component_impl already collects AssumedSystemRequirementsInfo (ASR) into the upstream lobster level, and both sibling rules (component_update,dependable_element) already accept the provider- only component_test's attribute schema was missing it. This blocked SEooCs from tracing component requirements directly to ASRs without a feature-requirements layer, failing with lobster error: unknown tracing target req .. --- bazel/rules/rules_score/private/component.bzl | 38 ++++++++++------- bazel/rules/rules_score/test/BUILD | 35 ++++++++++++++++ .../rules_score/test/unit_component_test.bzl | 41 +++++++++++++++++++ 3 files changed, 99 insertions(+), 15 deletions(-) diff --git a/bazel/rules/rules_score/private/component.bzl b/bazel/rules/rules_score/private/component.bzl index 001d6bf3..3fb4a4e3 100644 --- a/bazel/rules/rules_score/private/component.bzl +++ b/bazel/rules/rules_score/private/component.bzl @@ -159,12 +159,12 @@ def _component_impl(ctx): # and bubble up SphinxSourcesInfo from sub-components/units. # # Only ComponentRequirementsInfo-providing targets contribute their own - # rendered RST here. feature_requirements targets are commonly also listed - # in `requirements` (see below) purely so their .lobster file can resolve - # derived_from references from the component requirements; they are - # already rendered once at the dependable_element level, so re-rendering - # them per component would duplicate the feature requirements page across - # every component that references the same feature. + # rendered RST here. feature_requirements / assumed_system_requirements + # targets are commonly also listed in `requirements` (see below) purely so + # their .lobster file can resolve derived_from references from the component + # requirements; they are already rendered once at the dependable_element + # level, so re-rendering them per component would duplicate the upstream + # requirements page across every component that references the same item. # ------------------------------------------------------------------------- req_sphinx_files = [] for req_target in ctx.attr.requirements: @@ -181,7 +181,10 @@ def _component_impl(ctx): # ------------------------------------------------------------------------- # Lobster Tracing: collect .lobster files from component_requirements targets - # and feature_requirements targets (needed to resolve derived_from references). + # and from upstream requirements targets -- feature_requirements, or + # assumed_system_requirements when a SEooC traces component requirements + # directly to ASRs without a feature requirements layer. Both feed the + # config's upstream level, so derived_from references resolve either way. # ------------------------------------------------------------------------- req_lobster_files = [] req_lobster_transitive_files = [] @@ -367,8 +370,9 @@ _component_test = rule( ), "requirements": attr.label_list( default = [], - providers = [[ComponentRequirementsInfo], [FeatureRequirementsInfo]], - doc = "Component requirements artifacts (component_requirements or feature_requirements targets)", + providers = [[ComponentRequirementsInfo], [FeatureRequirementsInfo], [AssumedSystemRequirementsInfo]], + doc = "Component requirements artifacts (component_requirements, feature_requirements or " + + "assumed_system_requirements targets)", ), "components": attr.label_list( providers = [[ComponentInfo], [UnitInfo]], @@ -429,12 +433,16 @@ def component( name: The name of the component. Used as the target name. requirements: List of labels to component_requirements targets that define the requirements for this component. A - feature_requirements target may also be listed here so its - .lobster file is available to resolve derived_from references - from the component requirements; only component_requirements - targets contribute rendered RST to the component's Sphinx docs, - so listing a feature_requirements target does not duplicate it - in the generated documentation. + feature_requirements or assumed_system_requirements target may + also be listed here so its .lobster file is available to resolve + derived_from references from the component requirements; only + component_requirements targets contribute rendered RST to the + component's Sphinx docs, so listing an upstream requirements + target does not duplicate it in the generated documentation. + A SEooC that derives its component requirements directly from + Assumed System Requirements (without an intermediate feature + requirements layer) lists the assumed_system_requirements target + here. components: List of labels to nested component targets (for hierarchical component structures). tests: List of labels to Bazel test targets that verify the component diff --git a/bazel/rules/rules_score/test/BUILD b/bazel/rules/rules_score/test/BUILD index 527bdff9..70ef19af 100644 --- a/bazel/rules/rules_score/test/BUILD +++ b/bazel/rules/rules_score/test/BUILD @@ -135,6 +135,7 @@ load( ) load( ":unit_component_test.bzl", + "component_direct_asr_test", "component_excludes_feature_req_docs_test", "component_provider_test", "component_requirements_transitive_test", @@ -286,6 +287,14 @@ component_requirements( # (AoUs reach a dependable_element as `safety_measures` of its safety_analysis; see # :aou_root_cause_aous.) +# Component requirements tracing directly to an AssumedSystemReq, with no +# feature_requirements layer (used by :test_component_direct_asr). +component_requirements( + name = "comp_req_direct_asr", + srcs = ["fixtures/seooc_test/component_requirements_direct_asr.trlc"], + deps = [":asr_trlc"], +) + # - Architecture Design: wp__component_arch architectural_design( name = "arch_design", @@ -1349,6 +1358,24 @@ component( tests = [], # Empty for testing ) +# Test Component tracing straight to Assumed System Requirements, i.e. with no +# feature_requirements layer in between (see +# fixtures/seooc_test/component_requirements_direct_asr.trlc). The +# assumed_system_requirements target must be accepted in `requirements` so its +# .lobster file reaches the component's lobster config; otherwise lobster-trace +# fails with "unknown tracing target req TestSEooC.ASR_TEST_001". +component( + name = "test_component_direct_asr", + testonly = True, + components = [":test_unit"], + requirements = [ + ":comp_req_direct_asr", + ":asr_trlc", + ], + tags = ["manual"], + tests = [], +) + # Test Dependable Element. # maturity = "development": this fixture intentionally omits a # test_case_coverage.lock.yaml, so under the release traceability gate its @@ -2054,6 +2081,14 @@ component_excludes_feature_req_docs_test( target_under_test = ":test_component", ) +# Regression test for component() rejecting assumed_system_requirements targets +# in `requirements`, which blocked SEooCs that trace component requirements +# directly to ASRs (no feature requirements layer). +component_direct_asr_test( + name = "component_direct_asr_test", + target_under_test = ":test_component_direct_asr", +) + component_test_case_coverage_lock_test( name = "component_test_case_coverage_lock_test", target_under_test = ":test_component_with_test_case_coverage_lock", diff --git a/bazel/rules/rules_score/test/unit_component_test.bzl b/bazel/rules/rules_score/test/unit_component_test.bzl index 0e49d4e0..190e4e91 100644 --- a/bazel/rules/rules_score/test/unit_component_test.bzl +++ b/bazel/rules/rules_score/test/unit_component_test.bzl @@ -211,6 +211,46 @@ def _component_excludes_feature_req_docs_test_impl(ctx): component_excludes_feature_req_docs_test = analysistest.make(_component_excludes_feature_req_docs_test_impl) +def _component_direct_asr_test_impl(ctx): + """Test that a component whose component_requirements trace straight to + Assumed System Requirements -- with no feature_requirements layer -- can + list the assumed_system_requirements target in `requirements`, and that its + .lobster file reaches the generated lobster config. + + Regression test: the rule's `requirements` attribute used to only accept + [ComponentRequirementsInfo] / [FeatureRequirementsInfo], so passing an + assumed_system_requirements target failed analysis with "does not have + mandatory providers" even though the implementation already handled + AssumedSystemRequirementsInfo. Without the ASR .lobster in the config, + lobster-trace reports "unknown tracing target req .". + """ + env = analysistest.begin(ctx) + target_under_test = analysistest.target_under_test(env) + + asserts.true( + env, + ComponentInfo in target_under_test, + "Component tracing directly to ASRs should provide ComponentInfo", + ) + + # The ASR .lobster must be wired into the component's lobster pipeline as an + # upstream source, otherwise derived_from references cannot be resolved. + input_basenames = [] + for action in analysistest.target_actions(env): + for f in action.inputs.to_list(): + input_basenames.append(f.basename) + + asserts.true( + env, + "asr_trlc.lobster" in input_basenames, + "The assumed_system_requirements .lobster file should feed the " + + "component's lobster actions (inputs found: %s)" % input_basenames, + ) + + return analysistest.end(env) + +component_direct_asr_test = analysistest.make(_component_direct_asr_test_impl) + # ============================================================================ # Test Case Coverage Lock Tests # ============================================================================ @@ -338,6 +378,7 @@ def unit_component_test_suite(name): ":component_provider_test", ":component_sphinx_sources_test", ":component_excludes_feature_req_docs_test", + ":component_direct_asr_test", ":component_test_case_coverage_lock_test", ":component_requirements_transitive_test", ":test_case_coverage_lock_check_action_release_test",