Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9e422f8
Add Process Status Overview page with tooling columns
antonkri Apr 23, 2026
8805ada
Split process status overview into three separate table files
antonkri Apr 23, 2026
13687dc
Restore single combined table; tooling columns via tooling_definition…
antonkri Apr 23, 2026
b236a9c
WIP
antonkri May 4, 2026
d2fb752
tables for process are in a good shape
antonkri May 4, 2026
7035783
feat: add Lifecycle and Security/Crypto columns to feature_and_proces…
antonkri May 8, 2026
349af03
refactor: transpose implementation status tables — modules as rows, d…
antonkri May 8, 2026
4c302e6
docs(skill): fix 'add a column' → 'add a row' for new module instruct…
antonkri May 8, 2026
01df003
feat: add test file counts to PA5 table; fix Time comp-int to ✅ (3 fi…
antonkri May 8, 2026
46504df
feat: replace test file counts with actual test case counts in PA5 table
antonkri May 8, 2026
3dc1380
feat: add implementation LOC counts to Code column in PA4 table
antonkri May 8, 2026
b244e51
feat: add repo links to Code column in PA4 table
antonkri May 8, 2026
6798cbe
style: remove trailing newline in custom.css
antonkri May 8, 2026
eb71fb9
feat: add feature integration tests from reference_integration repo t…
antonkri May 8, 2026
4bb447a
fix: remove unreferenced RST footnote [*] causing CI warning
antonkri May 8, 2026
daf825a
docs: increase process status pie chart size to 840px for better visi…
antonkri May 12, 2026
b804e61
feat: add Static Code Analysis column to PA5 and update SKILL with 0%…
antonkri May 13, 2026
5dbb464
feat: add Dynamic Code Analysis column to PA5 table
antonkri May 13, 2026
616f647
style: expand content width on feature_and_process_status page for wi…
antonkri May 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
843 changes: 843 additions & 0 deletions .github/skills/module-phase-tracker/SKILL.md

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions process/_assets/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,33 @@
.score-grid .sd-card.card-ml4 .sd-card-footer a {
color: var(--card-body-text-color) !important;
}

/* Compact process area overview charts */
.compact-overview-wrapper {
overflow-x: auto;
}

.compact-overview-table td:nth-child(1),
.compact-overview-table th:nth-child(1),
.compact-overview-table td:nth-child(5),
.compact-overview-table th:nth-child(5),
.compact-overview-table td:nth-child(6),
.compact-overview-table th:nth-child(6) {
text-align: center;
vertical-align: middle;
}

.compact-overview-table td:has(img[id^="needpie-"]) {
min-width: 240px;
vertical-align: middle;
text-align: center;
}

.compact-overview-table td:has(img[id^="needpie-"]) img {
width: 240px;
max-width: none;
height: auto;
display: block;
margin: 0 auto;
}

59 changes: 59 additions & 0 deletions process/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,64 @@
html_static_path = ["_assets"]
html_css_files = ["custom.css"]

# Hide the "On this page" secondary sidebar for wide-content pages
html_theme_options = {
"secondary_sidebar_items": {
"**": ["page-toc"],
"standards/process_reqs_list/process_area_status_summary": [],
"standards/process_reqs_list/process_status_overview": [],
}
}

# :need:`{title}` is used in the needs templates to display the title of the need
needs_role_need_template = "{title}"

# Make the process/ directory importable so that filter functions
# referenced via :filter-func: in sphinx-needs directives can be found.
import sys as _sys
import os as _os
_sys.path.insert(0, _os.path.dirname(_os.path.abspath(__file__)))


def _patch_needpie_suppress_legend() -> None:
"""Suppress all in-chart legends in sphinx-needs needpie charts.

needpie auto-adds a legend whenever a slice is <5% or zero, even without
the :legend: option. Since a static legend is displayed above the table,
we replace axes.legend() with a no-op so no legend appears inside the charts.

We also patch save_matplotlib_figure to always overwrite existing SVG files,
bypassing the sphinx-needs env.images cache which would otherwise skip
regenerating images when the Sphinx environment pickle exists from a prior build.
"""
try:
import matplotlib.axes
matplotlib.axes.Axes.legend = lambda self, *args, **kwargs: None
except Exception:
pass

try:
import sphinx_needs.utils as _sn_utils
import sphinx_needs.directives.needpie as _needpie_mod
import os

_orig_save = _sn_utils.save_matplotlib_figure

def _save_always(app, figure, basename, fromdocname): # type: ignore[no-untyped-def]
# Remove cached entry so figure.savefig() is always called
builder = app.builder
for ext in ("svg", "png", "pdf"):
path = os.path.join(builder.outdir, builder.imagedir, f"{basename}.{ext}")
try:
del app.env.images[path] # type: ignore[attr-defined]
except (KeyError, TypeError, AttributeError):
pass
return _orig_save(app, figure, basename, fromdocname)

_sn_utils.save_matplotlib_figure = _save_always
_needpie_mod.save_matplotlib_figure = _save_always
except Exception:
pass


_patch_needpie_suppress_legend()
153 changes: 153 additions & 0 deletions process/needs_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# *******************************************************************************
# Copyright (c) 2025 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

"""
Custom filter functions for use with sphinx-needs :filter-func: option.
"""


def std_req_status_for_area(needs, results, arg1=""):
"""
filter_func for needpie: counts the tag-based compliance status distribution
of std_req needs referenced via `complies` from gd_req needs tagged with the
given process area tag.

Recognized tags (in priority order): ok, recommendation, open, action,
deviation, n/a. Needs with none of these tags are counted as "other".

arg1 = process area tag (e.g. requirements_engineering)
"""
area_tag = arg1.strip()
std_req_ids = set()
needs_by_id = {n["id"]: n for n in needs}
for need in needs:
if (
need.get("type") == "gd_req"
and not need.get("is_external", False)
and area_tag in need.get("tags", [])
):
for ref_id in need.get("complies", []):
if ref_id.startswith("std_req__iso26262__"):
std_req_ids.add(ref_id)
ok = recommendation = open_ = action = deviation = na = other = 0
for sid in std_req_ids:
n = needs_by_id.get(sid)
if n:
t = set(n.get("tags", []))
if "deviation" in t:
deviation += 1
elif "action" in t:
action += 1
elif "open" in t:
open_ += 1
elif "ok" in t:
ok += 1
elif "recommendation" in t:
recommendation += 1
elif "n/a" in t:
na += 1
else:
other += 1
results += [ok, recommendation, open_, action, deviation, na, other]


def wp_tag_status(needs, results, arg1=""):
"""
filter_func for needpie: counts the tag-based verification status distribution
of gd_req needs associated with one or more workflows (pipe-separated in arg1).

Tags (in priority order):
- done_automation → Automated
- prio_<X>_automation → Waiting for automation
- manual_prio_<X> → Inspection list
- (none of the above) → Other

arg1 = workflow id(s), pipe-separated (e.g. wf__foo or wf__foo|wf__bar)
"""
workflow_ids = [w.strip() for w in arg1.split("|") if w.strip()]
automated = waiting = inspection = other = 0
for need in needs:
if need.get("type") == "gd_req" and not need.get("is_external", False):
satisfies = need.get("satisfies", [])
if any(wf in satisfies for wf in workflow_ids):
tags = set(need.get("tags", []))
if "done_automation" in tags:
automated += 1
elif any(
t.startswith("prio_") and t.endswith("_automation")
for t in tags
):
waiting += 1
elif any(t.startswith("manual_prio_") for t in tags):
inspection += 1
else:
other += 1
results += [automated, waiting, inspection, other]


def area_verification_status(needs, results, arg1=""):
"""
filter_func for needpie: counts the tag-based verification status distribution
of gd_req needs tagged with the given process area tag, aggregated across all
workflows for that area.

Tags (in priority order):
- done_automation → Automated
- prio_<X>_automation → Waiting for automation
- manual_prio_<X> → Inspection list
- (none of the above) → Other

arg1 = process area tag (e.g. requirements_engineering)
"""
area_tag = arg1.strip()
automated = waiting = inspection = other = 0
for need in needs:
if (
need.get("type") == "gd_req"
and not need.get("is_external", False)
and area_tag in need.get("tags", [])
):
tags = set(need.get("tags", []))
if "done_automation" in tags:
automated += 1
elif any(
t.startswith("prio_") and t.endswith("_automation")
for t in tags
):
waiting += 1
elif any(t.startswith("manual_prio_") for t in tags):
inspection += 1
else:
other += 1
results += [automated, waiting, inspection, other]


def wp_done_automation_status(needs, results, arg1=""):
"""
filter_func for needpie: counts gd_req needs associated with one or more
workflows and splits them into done_automation vs. remaining requirements.

arg1 = workflow id(s), pipe-separated (e.g. wf__foo or wf__foo|wf__bar)
"""
workflow_ids = [w.strip() for w in arg1.split("|") if w.strip()]
done = rest = 0
for need in needs:
if need.get("type") == "gd_req" and not need.get("is_external", False):
satisfies = need.get("satisfies", [])
if any(wf in satisfies for wf in workflow_ids):
tags = set(need.get("tags", []))
if "done_automation" in tags:
done += 1
else:
rest += 1
results += [done, rest]
Loading
Loading