Skip to content

Commit 846ced5

Browse files
committed
fist draft
1 parent 37f4ca2 commit 846ced5

14 files changed

Lines changed: 921 additions & 9 deletions

docs/internals/requirements/requirements.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,34 @@ Testing
944944
* LOW
945945
* HIGH
946946

947+
.. tool_req:: Verification report schema contract
948+
:id: tool_req__docs_tvr_report_schema_contract
949+
:tags: Tool Verification Reports
950+
:implemented: PARTIAL
951+
:version: 1
952+
:parent_covered: NO
953+
:satisfies: gd_req__verification_reporting, gd_req__verification_report_archiving
954+
:source_code_link: scripts_bazel/verification_report_schema.json:1; scripts_bazel/verification_coverage_schema.json:1; scripts_bazel/verification_evidence_schema.json:1
955+
956+
Docs-as-Code shall provide machine-readable schema contracts for module verification
957+
reporting and report archiving.
958+
959+
.. note:: Schema files are in place; generation and enforcement logic is not yet implemented.
960+
961+
.. tool_req:: Verification section schema checks
962+
:id: tool_req__docs_tvr_section_schema_checks
963+
:tags: Tool Verification Reports
964+
:implemented: PARTIAL
965+
:version: 1
966+
:parent_covered: NO
967+
:satisfies: gd_req__verification_checks_extended
968+
:source_code_link: scripts_bazel/verification_coverage_schema.json:1; scripts_bazel/verification_evidence_schema.json:1
969+
970+
Docs-as-Code shall define machine-readable section-level schema contracts for
971+
verification coverage and evidence to support extended verification checks.
972+
973+
.. note:: Schema files are in place; check execution and report generation are not yet implemented.
974+
947975
⚙️ Process / Other
948976
###################
949977

scripts_bazel/BUILD

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,11 @@ py_binary(
4545
visibility = ["//visibility:public"],
4646
deps = [],
4747
)
48+
49+
py_binary(
50+
name = "verification_schema_sync_check",
51+
srcs = ["verification_schema_sync_check.py"],
52+
main = "verification_schema_sync_check.py",
53+
visibility = ["//visibility:public"],
54+
deps = [],
55+
)

scripts_bazel/tests/BUILD

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,12 @@ score_pytest(
4141
] + all_requirements,
4242
pytest_config = "//:pyproject.toml",
4343
)
44+
45+
score_pytest(
46+
name = "verification_schema_sync_check_test",
47+
srcs = ["verification_schema_sync_check_test.py"],
48+
deps = [
49+
"//scripts_bazel:verification_schema_sync_check",
50+
] + all_requirements,
51+
pytest_config = "//:pyproject.toml",
52+
)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
"""Tests for verification_schema_sync_check.py."""
15+
16+
from __future__ import annotations
17+
18+
import json
19+
import subprocess
20+
import sys
21+
from pathlib import Path
22+
23+
_MY_PATH = Path(__file__).parent
24+
_CHECK_SCRIPT = _MY_PATH.parent / "verification_schema_sync_check.py"
25+
26+
27+
def _write_template(tmp_path: Path, description: str) -> Path:
28+
path = tmp_path / "module_verification_report.rst"
29+
path.write_text(
30+
"""
31+
Verification Report contains:
32+
33+
.. list-table:: Verification report section contract fields
34+
:header-rows: 1
35+
:widths: 1 2 5
36+
37+
* - section_index
38+
- section_key
39+
- section_description
40+
* - 1
41+
- verification_coverage
42+
- DESCRIPTION_PLACEHOLDER
43+
""".replace("DESCRIPTION_PLACEHOLDER", description),
44+
encoding="utf-8",
45+
)
46+
return path
47+
48+
49+
def _write_schema(tmp_path: Path, description: str | None) -> Path:
50+
schema = {
51+
"properties": {
52+
"verification_coverage": {
53+
"$ref": "./verification_coverage_schema.json",
54+
}
55+
}
56+
}
57+
if description is not None:
58+
schema["properties"]["verification_coverage"]["description"] = description
59+
60+
path = tmp_path / "verification_report_schema.json"
61+
path.write_text(json.dumps(schema), encoding="utf-8")
62+
return path
63+
64+
65+
def _run_check(template_path: Path, schema_path: Path) -> subprocess.CompletedProcess:
66+
return subprocess.run(
67+
[
68+
sys.executable,
69+
_CHECK_SCRIPT,
70+
"--process-template",
71+
str(template_path),
72+
"--report-schema",
73+
str(schema_path),
74+
"--section-key",
75+
"verification_coverage",
76+
],
77+
capture_output=True,
78+
text=True,
79+
)
80+
81+
82+
def test_sync_check_passes_on_matching_description(tmp_path: Path) -> None:
83+
description = (
84+
"Coverage on requirements, architecture, and detailed design including "
85+
"test and inspection results."
86+
)
87+
template_path = _write_template(tmp_path, description)
88+
schema_path = _write_schema(tmp_path, description)
89+
90+
result = _run_check(template_path, schema_path)
91+
92+
assert result.returncode == 0
93+
assert "Schema sync check passed." in result.stdout
94+
95+
96+
def test_sync_check_fails_on_description_drift(tmp_path: Path) -> None:
97+
template_path = _write_template(
98+
tmp_path,
99+
"Coverage on requirements, architecture, and detailed design including test and inspection results.",
100+
)
101+
schema_path = _write_schema(
102+
tmp_path,
103+
"Coverage-focused sections of the S-CORE process verification report.",
104+
)
105+
106+
result = _run_check(template_path, schema_path)
107+
108+
assert result.returncode == 2
109+
assert "Schema sync check failed:" in result.stdout
110+
111+
112+
def test_sync_check_fails_on_missing_description(tmp_path: Path) -> None:
113+
template_path = _write_template(
114+
tmp_path,
115+
"Coverage on requirements, architecture, and detailed design including test and inspection results.",
116+
)
117+
schema_path = _write_schema(tmp_path, None)
118+
119+
result = _run_check(template_path, schema_path)
120+
121+
assert result.returncode == 2
122+
assert "schema description missing" in result.stderr

scripts_bazel/traceability_gate.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
CI gate → traceability_gate --metrics-json metrics.json [--min-* ...]
2323
2424
The gate never parses needs.json itself; it only reads the pre-computed
25-
schema-v1 metrics file produced by the docs build.
25+
schema-v2 metrics file produced by the docs build.
2626
"""
2727

2828
from __future__ import annotations
@@ -34,7 +34,7 @@
3434
from pathlib import Path
3535
from typing import Any
3636

37-
_SUPPORTED_SCHEMA_VERSION = "1"
37+
_SUPPORTED_SCHEMA_VERSION = "2"
3838

3939

4040
def _print_type_summary(need_type: str, metrics: dict[str, Any]) -> None:
@@ -125,7 +125,7 @@ def _check_type_thresholds(
125125
def main() -> int:
126126
parser = argparse.ArgumentParser(
127127
description=(
128-
"Read a traceability metrics JSON (schema v1) and enforce coverage "
128+
"Read a traceability metrics JSON (schema v2) and enforce coverage "
129129
"thresholds. Exits 0 on pass, 2 on threshold failure, 1 on input error."
130130
)
131131
)

scripts_bazel/traceability_metrics_schema.json

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"properties": {
1010
"schema_version": {
1111
"type": "string",
12-
"const": "1",
12+
"const": "2",
1313
"description": "Schema version. Bump when the shape changes incompatibly."
1414
},
1515
"generated_by": {
@@ -28,7 +28,13 @@
2828
"$defs": {
2929
"TypeMetrics": {
3030
"type": "object",
31-
"required": ["include_not_implemented", "include_external", "requirements", "tests"],
31+
"required": [
32+
"include_not_implemented",
33+
"include_external",
34+
"requirements",
35+
"tests",
36+
"process_requirements"
37+
],
3238
"additionalProperties": false,
3339
"properties": {
3440
"include_not_implemented": {
@@ -44,6 +50,9 @@
4450
},
4551
"tests": {
4652
"$ref": "#/$defs/TestMetrics"
53+
},
54+
"process_requirements": {
55+
"$ref": "#/$defs/ProcessRequirementMetrics"
4756
}
4857
}
4958
},
@@ -157,6 +166,45 @@
157166
}
158167
}
159168
},
169+
"ProcessRequirementMetrics": {
170+
"type": "object",
171+
"required": [
172+
"total",
173+
"linked",
174+
"linked_by_tool_requirements",
175+
"linked_by_tool_requirements_pct",
176+
"unlinked_ids"
177+
],
178+
"additionalProperties": false,
179+
"properties": {
180+
"total": {
181+
"type": "integer",
182+
"minimum": 0,
183+
"description": "Total number of process requirements in scope."
184+
},
185+
"linked": {
186+
"type": "integer",
187+
"minimum": 0,
188+
"description": "Process requirements linked by at least one tool requirement."
189+
},
190+
"linked_by_tool_requirements": {
191+
"type": "integer",
192+
"minimum": 0,
193+
"description": "Process requirements linked by tool requirements."
194+
},
195+
"linked_by_tool_requirements_pct": {
196+
"type": "number",
197+
"minimum": 0,
198+
"maximum": 100,
199+
"description": "linked_by_tool_requirements / total * 100, or 100 when total == 0."
200+
},
201+
"unlinked_ids": {
202+
"type": "array",
203+
"items": { "type": "string" },
204+
"description": "Sorted IDs of process requirements without a matching tool requirement."
205+
}
206+
}
207+
},
160208
"BrokenReference": {
161209
"type": "object",
162210
"required": ["testcase", "missing_need"],

0 commit comments

Comments
 (0)