2"""Validate the repository's option-aware user-facing reporting contract."""
4from __future__
import annotations
9from pathlib
import Path
12REPO_ROOT = Path(__file__).resolve().parents[2]
13SRC_DIR = REPO_ROOT /
"src"
14ALLOWED_DIRECT_C_OUTPUT = {
23 "Momentum Equation Solver",
24 "Initial Pseudo-CFL (Courant)",
25 "Newton-Krylov PETSc Controls",
26 "Pseudo-Time Controller : NOT APPLICABLE",
28 "Profiling Timestep Output",
30 "Solution Convergence Mode",
32CONTRACT_PATH = REPO_ROOT /
"tests" /
"tooling" /
"user_facing_reporting_contract.json"
33CLI_REQUIRED = (
"Momentum Solver: Dual Time Picard Jameson RK",
"Momentum Solver: Newton Krylov",
34 "Momentum Solver: Explicit RK (no pseudo-time controller)",
35 "Dual-Time Pseudo-Time Controls",
"Newton--Krylov Controls")
40 @brief Replace C comments while preserving source line positions.
41 @param[in] text C source text to normalize.
42 @return Source text with comments replaced by whitespace/newlines.
45 text = re.sub(
r"/\*.*?\*/",
lambda match:
"\n" * match.group(0).count(
"\n"), text, flags=re.DOTALL)
46 return re.sub(
r"//[^\n]*",
"", text)
51 @brief Return raw C console emissions outside their approved rendering modules.
52 @return Human-readable findings for every disallowed emission.
55 findings: list[str] = []
56 pattern = re.compile(
r"\b(?:PetscPrintf|PetscSynchronizedPrintf|printf)\s*\(")
57 for path
in sorted(SRC_DIR.glob(
"*.c")):
58 if path.name
in ALLOWED_DIRECT_C_OUTPUT:
60 stripped =
strip_c_comments(path.read_text(encoding=
"utf-8", errors=
"ignore"))
61 for match
in pattern.finditer(stripped):
62 line = stripped.count(
"\n", 0, match.start()) + 1
64 f
"{path.relative_to(REPO_ROOT)}:{line}: raw console output must use the logging policy "
65 "or be moved to an approved reporting surface."
72 @brief Return missing reporting-contract fragments for one user-facing surface.
73 @param[in] path Source file containing the surface.
74 @param[in] fragments Required literal contract fragments.
75 @param[in] surface Human-readable surface name for failures.
76 @return Findings for missing fragments.
79 text = path.read_text(encoding=
"utf-8")
80 return [f
"{surface}: missing required option-aware reporting fragment {fragment!r}."
81 for fragment
in fragments
if fragment
not in text]
86 @brief Verify that every declared CLI command has a parser, dispatch handler, and contextual message.
87 @param[in] contract Parsed user-facing reporting contract mapping.
88 @return Findings for missing CLI command-reporting contract elements.
91 cli_text = (REPO_ROOT /
"picurv_cli" /
"cli.py").read_text(encoding=
"utf-8")
92 core_text = (REPO_ROOT /
"picurv_cli" /
"core.py").read_text(encoding=
"utf-8")
93 findings: list[str] = []
94 for command, entry
in contract[
"cli_commands"].items():
95 for field, text, surface
in (
96 (
"parser", cli_text,
"CLI parser"),
97 (
"handler", core_text,
"CLI handler"),
98 (
"context", cli_text + core_text,
"CLI context"),
100 if entry[field]
not in text:
101 findings.append(f
"{surface} for '{command}': missing contract fragment {entry[field]!r}.")
107 @brief Audit C banner, CLI summaries, and direct-output routing.
108 @return Process status code.
112 contract = json.loads(CONTRACT_PATH.read_text(encoding=
"utf-8"))
114 REPO_ROOT / contract[
"banner"][
"source"], tuple(contract[
"banner"][
"required_fragments"]),
"C startup banner"
116 findings.extend(
require_fragments(REPO_ROOT /
"picurv_cli" /
"core.py", CLI_REQUIRED,
"Python CLI/summarize"))
119 print(
"\n".join(findings), file=sys.stderr)
121 print(
"User-facing reporting audit passed.")
125if __name__ ==
"__main__":
126 raise SystemExit(
main())
list[str] require_fragments(Path path, tuple[str,...] fragments, str surface)
Return missing reporting-contract fragments for one user-facing surface.
int main()
Audit C banner, CLI summaries, and direct-output routing.
list[str] audit_cli_contract(dict contract)
Verify that every declared CLI command has a parser, dispatch handler, and contextual message.
str strip_c_comments(str text)
Replace C comments while preserving source line positions.
list[str] audit_direct_c_output()
Return raw C console emissions outside their approved rendering modules.