2"""Enforce the documentation obligations each subsystem lifecycle status carries."""
4from __future__
import annotations
9from pathlib
import Path
12REPO_ROOT = Path(__file__).resolve().parents[2]
13RECORDS = REPO_ROOT /
"tests" /
"tooling" /
"subsystem_records.json"
14PAGE_TYPES = REPO_ROOT /
"tests" /
"tooling" /
"page_types.json"
15FAMILIES = REPO_ROOT /
"tests" /
"tooling" /
"capability_families.json"
16PAGE_DIRS = (
"docs/pages",
"docs")
21LADDER = (
"planned",
"internal",
"experimental",
"supported")
24 "planned": (
"purpose",
"intended_scope",
"design_owner",
"not_implemented_status"),
25 "internal": (
"scope_boundary",
"architecture_boundary",
"dependencies",
26 "developer_entry_points"),
27 "experimental": (
"configuration",
"selection_guidance",
"observability",
"limitations",
28 "safe_use_boundaries"),
29 "supported": (
"evidence",
"lifecycle_and_restart",
"operations",
"troubleshooting",
30 "examples",
"complete_reference"),
35TERMINAL_OBLIGATIONS = {
36 "known-defective": (
"defect_disclosure",
"defect_scope_record",
"safe_use_boundaries",
38 "deprecated": (
"migration_path",
"replacement",
"compatibility_period",
"removal_policy"),
39 "removed": (
"history_record",
"rejection_behavior"),
43NON_INHERITED = (
"not_implemented_status",)
44NEEDS_PEAK = (
"known-defective",
"deprecated",
"removed")
46INHERITS_LADDER = (
"known-defective",
"deprecated")
48VALID_STATUSES = tuple(LADDER) + tuple(TERMINAL_OBLIGATIONS)
59 None: set(VALID_STATUSES) - {
"removed"},
60 "planned": {
"planned",
"internal",
"experimental",
"supported",
"removed"},
61 "internal": {
"internal",
"experimental",
"supported",
"known-defective",
"deprecated"},
62 "experimental": {
"experimental",
"supported",
"known-defective",
"deprecated"},
63 "supported": {
"supported",
"known-defective",
"deprecated"},
64 "known-defective": {
"known-defective",
"experimental",
"supported",
"deprecated",
"removed"},
65 "deprecated": {
"deprecated",
"removed"},
66 "removed": {
"removed"},
69VALID_VISIBILITY = (
"internal",
"public")
73 "numerical_method",
"user_selector",
"units_and_nondimensionalization",
74 "artifact_topology",
"persistent_restart_state",
"determinism_and_reproducibility",
75 "mpi_distributed_execution",
"external_service",
"security_credentials",
76 "generated_artifact",
"file_format",
"destructive_scope",
"backward_compatibility",
77 "scientific_verification",
80RECORD_KEYS = {
"id",
"title",
"status",
"visibility",
"previous_status",
"peak_status",
81 "proposed_status",
"promotion_rationale",
"capability_families",
82 "obligations",
"concerns",
"note"}
85FILLER_REASONS = {
"n/a",
"na",
"none",
"not applicable",
"no",
"-",
"tbd"}
90 @brief Every documentation page id with the anchors it defines.
91 @return Mapping of page id to the set of `@section`, `@subsection`, and `@anchor` names.
94 for directory
in PAGE_DIRS:
95 for markdown
in sorted((REPO_ROOT / directory).glob(
"*.md")):
96 text = markdown.read_text(encoding=
"utf-8")
97 match = re.search(
r"^@page\s+(\S+)", text, re.M)
98 if not match
or match.group(1).startswith(
"<"):
100 anchors = set(re.findall(
r"^@(?:section|subsection|subsubsection|anchor)\s+(\S+)",
102 index[match.group(1)] = anchors
108 @brief The obligation ids a record owes.
110 @details A record may declare a `proposed_status` above its claimed one. That is
111 how a subsystem documented to a higher bar waits for the owner to decide
112 whether it has actually earned it: obligations are checked against the
113 proposal, so the writing is held to the higher standard, while the status
114 the documentation publishes stays conservative until a human agrees.
115 @param[in] record One subsystem record.
116 @return Ordered tuple of obligation ids.
118 status = record.get(
"proposed_status")
or record.get(
"status")
121 for rung
in LADDER[: LADDER.index(status) + 1]:
122 owed.extend(LADDER_OBLIGATIONS[rung])
124 if status
in INHERITS_LADDER:
125 peak = record.get(
"peak_status")
127 for rung
in LADDER[: LADDER.index(peak) + 1]:
128 owed.extend(LADDER_OBLIGATIONS[rung])
129 owed.extend(TERMINAL_OBLIGATIONS.get(status, ()))
130 if status !=
"planned":
131 owed = [key
for key
in owed
if key
not in NON_INHERITED]
133 return tuple(dict.fromkeys(owed))
137 public: bool) -> list:
139 @brief Verify one obligation or concern is genuinely answered.
141 @details An answer is a documentation reference that resolves, or a stated reason
142 for non-applicability, or a literal value where the obligation is a fact
143 rather than prose. An empty or filler answer is a violation.
144 @param[in] context Record id, for messages.
145 @param[in] key Obligation or concern id.
146 @param[in] spec The declared answer.
147 @param[in] pages Page index from page_index().
148 @param[in] published Ids of the pages the site publishes.
149 @param[in] public Whether the subsystem is publicly visible.
150 @return List of violation strings.
152 if not isinstance(spec, dict):
153 return [f
"{context}: '{key}' must be an object, got {type(spec).__name__}"]
155 if "not_applicable" in spec:
156 reason = str(spec[
"not_applicable"]).strip()
157 if reason.lower().rstrip(
".")
in FILLER_REASONS
or len(reason) < MIN_REASON_CHARS:
159 f
"{context}: '{key}' is declared not applicable without a stated reason "
160 f
"({reason!r}). A reasoned N/A is accepted; a bare one is not"
164 if not str(spec[
"value"]).strip():
165 problems.append(f
"{context}: '{key}' declares an empty value")
167 page = spec.get(
"page")
170 f
"{context}: '{key}' is unsatisfied - give it a page reference, a value, or a "
171 f
"reasoned not_applicable"
174 if page
not in pages:
175 problems.append(f
"{context}: '{key}' cites page '{page}', which does not exist")
177 anchor = spec.get(
"anchor")
178 if anchor
and anchor
not in pages[page]:
180 f
"{context}: '{key}' cites anchor '{anchor}' on page '{page}', which does not "
183 if public
and page
not in published:
185 f
"{context}: '{key}' cites '{page}', which is not a published page, but the "
186 f
"subsystem is publicly visible"
191def validate(records: list, pages: dict, families: dict, published: set) -> list:
193 @brief Validate every subsystem record against the lifecycle contract.
194 @param[in] records Subsystem records.
195 @param[in] pages Page index from page_index().
196 @param[in] families Capability family metadata, keyed by family id.
197 @param[in] published Ids of the pages the site publishes.
198 @return List of violation strings; empty means the contract holds.
202 for record
in records:
203 identifier = record.get(
"id")
205 problems.append(
"a record declares no id")
207 if identifier
in seen:
208 problems.append(f
"{identifier}: declared more than once")
211 unknown = set(record) - RECORD_KEYS
213 problems.append(f
"{identifier}: unknown field(s) {sorted(unknown)}")
215 status = record.get(
"status")
216 if status
not in VALID_STATUSES:
218 f
"{identifier}: status {status!r} is not one of {list(VALID_STATUSES)}"
222 visibility = record.get(
"visibility")
223 if visibility
not in VALID_VISIBILITY:
225 f
"{identifier}: visibility {visibility!r} is not one of "
226 f
"{list(VALID_VISIBILITY)}"
229 if status ==
"internal" and visibility !=
"internal":
231 f
"{identifier}: status 'internal' contradicts visibility 'public'; a "
232 f
"subsystem the user can reach is at least experimental"
235 previous = record.get(
"previous_status",
None)
236 if previous
is not None and previous
not in VALID_STATUSES:
237 problems.append(f
"{identifier}: previous_status {previous!r} is not a valid status")
238 elif status
not in TRANSITIONS[previous]:
240 f
"{identifier}: {previous or 'a new record'} -> '{status}' is not a valid "
241 f
"lifecycle transition (allowed: {sorted(TRANSITIONS[previous])})"
244 proposed = record.get(
"proposed_status")
245 if proposed
is not None:
246 if proposed
not in LADDER:
248 f
"{identifier}: proposed_status {proposed!r} must name a rung of "
251 elif status
not in LADDER
or LADDER.index(proposed) <= LADDER.index(status):
253 f
"{identifier}: proposed_status '{proposed}' is not above the claimed "
254 f
"status '{status}'; a proposal that is not a promotion is noise"
256 elif not record.get(
"promotion_rationale"):
258 f
"{identifier}: proposes '{proposed}' but gives no promotion_rationale. "
259 f
"Say what the owner is being asked to confirm"
262 if status
in NEEDS_PEAK:
263 peak = record.get(
"peak_status")
264 if peak
not in LADDER:
266 f
"{identifier}: status '{status}' requires peak_status naming the highest "
267 f
"rung it reached, one of {list(LADDER)}"
269 elif record.get(
"peak_status")
is not None:
271 f
"{identifier}: peak_status applies only to {list(NEEDS_PEAK)}, not '{status}'"
274 obligations = record.get(
"obligations")
or {}
277 if key
not in obligations:
279 f
"{identifier}: status '{status}' owes '{key}', which is not declared"
284 visibility ==
"public")
286 for key
in sorted(set(obligations) - set(owed)):
288 f
"{identifier}: declares obligation '{key}', which status '{status}' does not "
289 f
"owe; remove it or claim the status that owes it"
292 concerns = record.get(
"concerns")
or {}
293 for key
in sorted(concerns):
294 if key
not in VALID_CONCERNS:
296 f
"{identifier}: concern '{key}' is not in the concern vocabulary of "
297 f
"64_Documentation_Extension_Framework"
302 visibility ==
"public")
306 for family_id
in record.get(
"capability_families", []):
307 family = families.get(family_id)
310 f
"{identifier}: cites capability family '{family_id}', which is not "
314 if status !=
"planned":
317 name
for name, meta
in family.get(
"value_metadata", {}).items()
318 if (meta
or {}).get(
"status") ==
"supported"
322 f
"{identifier}: is 'planned' but family '{family_id}' already offers "
323 f
"supported value(s) {live}; a planned subsystem must not appear as "
324 f
"supported behavior"
331 @brief Report subsystem lifecycle violations.
332 @return Process status code.
334 document = json.loads(RECORDS.read_text(encoding=
"utf-8"))
335 records = document[
"subsystems"]
336 published = set(json.loads(PAGE_TYPES.read_text(encoding=
"utf-8"))[
"assignments"])
339 for family
in json.loads(FAMILIES.read_text(encoding=
"utf-8"))[
"families"]
343 print(
"Subsystem lifecycle violations:", file=sys.stderr)
344 for problem
in problems:
345 print(f
" {problem}", file=sys.stderr)
347 "\nObligations grow with the status a subsystem claims. See\n"
348 "64_Documentation_Extension_Framework section 4. Lower the claimed status, or\n"
349 "write the documentation that status owes - do not add empty prose to pass.",
354 from collections
import Counter
355 spread = Counter(record[
"status"]
for record
in records)
356 summary =
", ".join(f
"{count} {status}" for status, count
in sorted(spread.items()))
357 print(f
"Subsystem lifecycle audit passed: {len(records)} subsystem(s) ({summary}).")
358 proposals = [r
for r
in records
if r.get(
"proposed_status")]
360 print(f
"\n{len(proposals)} promotion(s) awaiting the owner's decision. The "
361 f
"documentation meets the higher bar; whether the subsystem has earned "
362 f
"the status is a human judgement this gate cannot make:")
363 for record
in proposals:
364 print(f
" {record['id']}: {record['status']} -> {record['proposed_status']}")
365 print(f
" {record['promotion_rationale']}")
369if __name__ ==
"__main__":
370 raise SystemExit(
main())
dict page_index()
Every documentation page id with the anchors it defines.
list check_satisfaction(str context, str key, spec, dict pages, set published, bool public)
Verify one obligation or concern is genuinely answered.
tuple required_obligations(dict record)
The obligation ids a record owes.
int main()
Report subsystem lifecycle violations.
list validate(list records, dict pages, dict families, set published)
Validate every subsystem record against the lifecycle contract.