Skip to content

Expose AoUs (including chain-forwarded ones) via TrlcProviderInfo - #474

Open
LittleHuba wants to merge 5 commits into
mainfrom
ulhu_aou_attempt_1
Open

LittleHuba wants to merge 5 commits into
mainfrom
ulhu_aou_attempt_1

Conversation

@LittleHuba

Copy link
Copy Markdown
Contributor

dependable_element now exposes both its own and chain-forwarded Assumptions of Use (AoUs) as TRLC records via TrlcProviderInfo, so downstream requirements targets can reference them directly in derived_from without needing visibility into the AoU's original owner.

A raw ScoreReq.AoU record must never leave the TRLC compilation of the assumptions_of_use target that authored it: exposing it verbatim to any other target would look, to any tooling walking the requirements model, like a second, independently authored assumption needing its own control-measure/safety-analysis linkage, when it is really just a forwarding/exposure placeholder. So every AoU exposed externally -- whether it is a dependable_element's own AoU (first-hop exposure, expose_own_aou_trlc.py) or one it received and is chain-forwarding further (filter_forwarded_trlc.py) -- is retyped to a new ScoreReq. ForwardedAoU record (same package + record name, a justification field injected), keeping every derived_from reference resolvable no matter how many hops away from the original owner it is.

Preserving identity across hops means the same AoU can legitimately reach one TRLC parse via more than one path (a "diamond": e.g. a consumer depends both on the AoU's owner and on an intermediate element that chain-forwards it). TRLC's own duplicate-definition check keys on package + record name alone, not on type, so this would otherwise be rejected as a duplicate definition. dedupe_aou_trlc.py resolves this automatically wherever TrlcProviderInfo is merged across a deps list (dependable_element.bzl and requirements.bzl), collapsing any duplicate AoU/ForwardedAoU identity down to a single kept declaration before it ever reaches TRLC.

  • trlc/config/score_requirements_model.rsl: add ForwardedAoU type extending ControlMeasure; extend CompReqSourceId.item.
  • src/trlc_record_utils.py: shared .trlc parsing/retyping helpers used by filter_forwarded_trlc.py, expose_own_aou_trlc.py, and dedupe_aou_trlc.py.
  • src/filter_forwarded_trlc.py: retype chain-forwarded AoU/ForwardedAoU records to ForwardedAoU, hard-fail on unmatched aou_forwarding.yaml entries.
  • src/expose_own_aou_trlc.py: retype a dependable_element's own AoU records to ForwardedAoU for first-hop external exposure.
  • src/dedupe_aou_trlc.py + private/aou_trlc_dedupe.bzl: deduplicate AoU/ForwardedAoU records reaching one TRLC parse via more than one dependency path (diamond dependencies).
  • private/dependable_element.bzl: own_aou_trlc and received_aou_trlc_reqs_list now go through the new retype/dedupe actions before being exposed via TrlcProviderInfo.
  • private/requirements.bzl: dedupe merged TrlcProviderInfo.reqs/.deps across a target's own deps before compiling.
  • providers.bzl, docs/user_guide/assumptions_of_use.rst, docs/rule_reference.rst: document the ForwardedAoU synthesis and diamond deduplication guarantees.
  • New tests: test_dedupe_aou_trlc.py, test_expose_own_aou_trlc.py, updated test_filter_forwarded_trlc.py, and a permanent diamond- dependency regression fixture (component_requirements_diamond_aou).

@github-actions

Copy link
Copy Markdown

Coverage Report

Coverage report was generated.

Full report can be downloaded from the CI artifacts (expand Artifacts at the bottom of the run).

Overall coverage rate:

lines......: 86.2%
functions......: 55.0%

LittleHuba and others added 5 commits September 21, 2026 09:51
dependable_element now exposes both its own and chain-forwarded
Assumptions of Use (AoUs) as TRLC records via TrlcProviderInfo, so
downstream requirements targets can reference them directly in
derived_from without needing visibility into the AoU's original owner.

A raw ScoreReq.AoU record must never leave the TRLC compilation of the
assumptions_of_use target that authored it: exposing it verbatim to any
other target would look, to any tooling walking the requirements model,
like a second, independently authored assumption needing its own
control-measure/safety-analysis linkage, when it is really just a
forwarding/exposure placeholder. So every AoU exposed externally --
whether it is a dependable_element's own AoU (first-hop exposure,
expose_own_aou_trlc.py) or one it received and is chain-forwarding
further (filter_forwarded_trlc.py) -- is retyped to a new ScoreReq.
ForwardedAoU record (same package + record name, a justification field
injected), keeping every derived_from reference resolvable no matter how
many hops away from the original owner it is.

Preserving identity across hops means the same AoU can legitimately
reach one TRLC parse via more than one path (a "diamond": e.g. a
consumer depends both on the AoU's owner and on an intermediate element
that chain-forwards it). TRLC's own duplicate-definition check keys on
package + record name alone, not on type, so this would otherwise be
rejected as a duplicate definition. dedupe_aou_trlc.py resolves this
automatically wherever TrlcProviderInfo is merged across a deps list
(dependable_element.bzl and requirements.bzl), collapsing any duplicate
AoU/ForwardedAoU identity down to a single kept declaration before it
ever reaches TRLC.

- trlc/config/score_requirements_model.rsl: add ForwardedAoU type
  extending ControlMeasure; extend CompReqSourceId.item.
- src/trlc_record_utils.py: shared .trlc parsing/retyping helpers used
  by filter_forwarded_trlc.py, expose_own_aou_trlc.py, and
  dedupe_aou_trlc.py.
- src/filter_forwarded_trlc.py: retype chain-forwarded AoU/ForwardedAoU
  records to ForwardedAoU, hard-fail on unmatched aou_forwarding.yaml
  entries.
- src/expose_own_aou_trlc.py: retype a dependable_element's own AoU
  records to ForwardedAoU for first-hop external exposure.
- src/dedupe_aou_trlc.py + private/aou_trlc_dedupe.bzl: deduplicate
  AoU/ForwardedAoU records reaching one TRLC parse via more than one
  dependency path (diamond dependencies).
- private/dependable_element.bzl: own_aou_trlc and
  received_aou_trlc_reqs_list now go through the new retype/dedupe
  actions before being exposed via TrlcProviderInfo.
- private/requirements.bzl: dedupe merged TrlcProviderInfo.reqs/.deps
  across a target's own deps before compiling.
- providers.bzl, docs/user_guide/assumptions_of_use.rst,
  docs/rule_reference.rst: document the ForwardedAoU synthesis and
  diamond deduplication guarantees.
- New tests: test_dedupe_aou_trlc.py, test_expose_own_aou_trlc.py,
  updated test_filter_forwarded_trlc.py, and a permanent diamond-
  dependency regression fixture (component_requirements_diamond_aou).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
component_requirements_chain_aou_negative.trlc was missing the required
Eclipse Foundation copyright header, causing the copyright-check CI job
to fail on PR #474.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The test/ Bazel module (a separate module from the repo root, used for
rules_score's own integration fixtures) had a bare 'llvm.toolchain()'
extension usage with no matching 'llvm.sysroot()' call, unlike the root
MODULE.bazel. This made local C++ compiles in this module (e.g.
flatbuffers' flatc) fail with 'features.h file not found', since libc
headers resolved against the host instead of a pinned sysroot -- masking
real target failures behind an unrelated toolchain error whenever
reproducing CI issues locally.

Mirror the root MODULE.bazel's hermetic sysroot setup (apt.install +
sysroot_from_lock + llvm.sysroot()), using uniquely-named repos
(test_tooling_sysroot*) to avoid a bzlmod module-extension singleton
collision with the root module's own identically-named apt.install(),
and adopt the same llvm.toolchain() compile_flags/extra_link_libs as the
root module for consistency.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…chitecture fixture

test_dependable_element_aou_middle previously reused ':arch_design_elem',
whose .puml only declares a 'test_dependable_element' package. This
passed analysis only because the (also-reusing) coverage fixtures are
tagged 'manual' and never have their '_index' validation actually run;
since this fixture is not manual, its '_index' target failed PlantUML
architecture validation with 'Package
"test_dependable_element_aou_middle" from Bazel not found in the
PlantUML component diagram' -- the first thing masking the real CI
failure when reproducing PR #474 locally.

Add a dedicated fixtures/test_dependable_element_aou_middle.puml (package
name matching the label) and a new arch_design_elem_aou_middle
architectural_design target, and point the dependable_element at it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ag namespace

'Forwarded AoUs' marker items (build_forwarded_markers) previously
derived their tag by string-appending '__forwarded' onto the matched
item's tag text, e.g. Tracing_Tag("req", f"{item.tag.tag}__forwarded",
item.tag.version). This both implied the marker forks/derives a second
identity from the AoU (it does not -- it is a distinct bookkeeping
record for a forwarding decision, referencing the original via 'refs')
and was outright buggy whenever the matched AoU id already contained an
'@Version' suffix: Tracing_Tag.from_text() splits on the *first* '@' it
finds when a marker is read back from its .lobster JSON file, so the
suffixed tag collapsed back onto the *original*, unsuffixed AoU tag on
read-back, silently colliding with it in Tracing_Tag.key() (which
ignores version). This produced 'duplicate definition' failures from
lobster-report for any real fixture whose AoUs carry a version, as seen
in PR #474's rules_score_tests CI failure.

Fix by giving the marker a completely independent Tracing_Tag namespace
('aou_forwarding_marker' instead of 'req') while keeping the tag *text*
identical to the original -- Tracing_Tag.key() is namespace + " " + tag,
so a distinct namespace alone guarantees no collision, without ever
mangling or suffixing the AoU's own tag text.

Add a regression test that round-trips a marker built from a versioned
AoU through actual .lobster JSON write/read (lobster_write/lobster_read)
to lock in the fix at the same layer where the original bug manifested.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Coverage Report

Coverage report was generated.

Full report can be downloaded from the CI artifacts (expand Artifacts at the bottom of the run).

Overall coverage rate:

lines......: 86.2%
functions......: 55.0%

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant