From 9dbca09c45437e789e2edbf5a69adcc3e4805813 Mon Sep 17 00:00:00 2001 From: Anton Krivoborodov Date: Wed, 7 Oct 2026 07:36:42 +0000 Subject: [PATCH] feat(platform-report): list requirements without in-scope references The reference coverage pies show *how many* requirements are not referenced by any lower-level requirement, but not *which* ones. Add a collapsed table next to each pie that lists exactly those requirements: - Stakeholder section: stakeholder requirements not referenced by any in-scope feature requirement. - Per feature: feature requirements not referenced by any in-scope component requirement. Both tables are filtered by the same pre-scoped ID lists that feed the pies (`ns_stkh_ref.missing` / `ns_feat_ref.missing`), so chart and table cannot disagree. The report version scoping therefore applies to the tables as well: a requirement referenced only from outside the report's `report_version` still counts as a gap. The tables are omitted entirely when there is no gap, so an empty table never shows up. Adds an end-to-end test rendering the report, covering the case where the only reference comes from an out-of-scope requirement. --- .../tests/test_needs_templates.py | 117 ++++++++++++++++++ .../platform_verification_report.need | 28 +++++ 2 files changed, 145 insertions(+) diff --git a/src/extensions/score_sphinx_needs_templates/tests/test_needs_templates.py b/src/extensions/score_sphinx_needs_templates/tests/test_needs_templates.py index 2bdf8ec18..e088710a2 100644 --- a/src/extensions/score_sphinx_needs_templates/tests/test_needs_templates.py +++ b/src/extensions/score_sphinx_needs_templates/tests/test_needs_templates.py @@ -315,3 +315,120 @@ def test_tool_qualification_matrix_groups_shared_requirements( ) assert '
' not in html assert '
' not in html + + +def test_platform_report_gap_table_is_report_version_scoped( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """The gap table lists requirements lacking an *in-scope* reference. + + A stakeholder requirement that is only referenced by a feature requirement + outside the report's ``report_version`` counts as a gap, because the + reference coverage pie classifies it as "not referenced" too. Both are + rendered from the same pre-scoped ID list, so they cannot disagree. + """ + monkeypatch.setenv("BUILD_WORKSPACE_DIRECTORY", str(tmp_path)) + (tmp_path / "conf.py").write_text( + """ +extensions = [ + "sphinx_needs", + "score_sphinx_needs_templates", + "score_metamodel", + "sphinx_design", +] +master_doc = "index" +needs_id_regex = r"^[a-zA-Z0-9_]+$" +""", + encoding="utf-8", + ) + (tmp_path / "index.rst").write_text( + """ +.. workproduct:: Platform report work product + :id: wp__platform_report + :status: valid + +.. document:: Platform verification report + :id: doc__platform_report + :status: valid + :safety: ASIL_B + :security: NO + :realizes: wp__platform_report + :report_version: v1.0 + :post_template: platform_verification_report + +.. stkh_req:: Referenced stakeholder requirement + :id: stkh_req__referenced + :reqtype: Functional + :safety: ASIL_B + :security: NO + :status: valid + :rationale: Referenced by an in-scope feature requirement. + :valid_from: v0.8 + + The platform shall satisfy the referenced stakeholder need. + +.. stkh_req:: Stakeholder requirement referenced out of scope only + :id: stkh_req__only_out_of_scope + :reqtype: Functional + :safety: ASIL_B + :security: NO + :status: valid + :rationale: Referenced only by an out-of-scope feature requirement. + :valid_from: v0.8 + + The platform shall satisfy the out-of-scope referenced stakeholder need. + +.. feat:: Scoped feature + :id: feat__scoped + :security: NO + :safety: ASIL_B + :status: valid + +.. feat_req:: In-scope feature requirement + :id: feat_req__in_scope + :reqtype: Functional + :security: NO + :safety: ASIL_B + :status: valid + :satisfied_by: feat__scoped + :derived_from: stkh_req__referenced + :valid_from: v0.8 + + This requirement is inside the report version scope. + +.. feat_req:: Out-of-scope feature requirement + :id: feat_req__out_of_scope + :reqtype: Functional + :security: NO + :safety: ASIL_B + :status: valid + :satisfied_by: feat__scoped + :derived_from: stkh_req__only_out_of_scope + :valid_from: v2.0 + + This requirement is outside the report version scope. +""", + encoding="utf-8", + ) + + app = SphinxTestApp( + srcdir=tmp_path, + outdir=tmp_path / "_build", + buildername="html", + freshenv=True, + ) + try: + app.build(force_all=True) + html = (app.outdir / "index.html").read_text(encoding="utf-8") + finally: + app.cleanup() + + assert "Not referenced by feature requirements" in html + gap_table = html.split("Not referenced by feature requirements", 1)[1].split( + '