PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Functions | Variables
audit_subsystem_lifecycle Namespace Reference

Functions

dict page_index ()
 Every documentation page id with the anchors it defines.
 
tuple required_obligations (dict record)
 The obligation ids a record owes.
 
list check_satisfaction (str context, str key, spec, dict pages, set published, bool public)
 Verify one obligation or concern is genuinely answered.
 
list validate (list records, dict pages, dict families, set published)
 Validate every subsystem record against the lifecycle contract.
 
int main ()
 Report subsystem lifecycle violations.
 

Variables

 REPO_ROOT = Path(__file__).resolve().parents[2]
 
str RECORDS = REPO_ROOT / "tests" / "tooling" / "subsystem_records.json"
 
str PAGE_TYPES = REPO_ROOT / "tests" / "tooling" / "page_types.json"
 
str FAMILIES = REPO_ROOT / "tests" / "tooling" / "capability_families.json"
 
tuple PAGE_DIRS = ("docs/pages", "docs")
 
tuple LADDER = ("planned", "internal", "experimental", "supported")
 
dict LADDER_OBLIGATIONS
 
dict TERMINAL_OBLIGATIONS
 
tuple NON_INHERITED = ("not_implemented_status",)
 
tuple NEEDS_PEAK = ("known-defective", "deprecated", "removed")
 
tuple INHERITS_LADDER = ("known-defective", "deprecated")
 
 VALID_STATUSES = tuple(LADDER) + tuple(TERMINAL_OBLIGATIONS)
 
dict TRANSITIONS
 
tuple VALID_VISIBILITY = ("internal", "public")
 
tuple VALID_CONCERNS
 
dict RECORD_KEYS
 
int MIN_REASON_CHARS = 30
 
dict FILLER_REASONS = {"n/a", "na", "none", "not applicable", "no", "-", "tbd"}
 

Detailed Description

Enforce the documentation obligations each subsystem lifecycle status carries.

Function Documentation

◆ page_index()

dict audit_subsystem_lifecycle.page_index ( )

Every documentation page id with the anchors it defines.

Returns
Mapping of page id to the set of @section, @subsection, and @anchor names.

Definition at line 88 of file audit_subsystem_lifecycle.py.

88def page_index() -> dict:
89 """!
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.
92 """
93 index: dict = {}
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("<"):
99 continue
100 anchors = set(re.findall(r"^@(?:section|subsection|subsubsection|anchor)\s+(\S+)",
101 text, re.M))
102 index[match.group(1)] = anchors
103 return index
104
105
Here is the caller graph for this function:

◆ required_obligations()

tuple audit_subsystem_lifecycle.required_obligations ( dict  record)

The obligation ids a record owes.

A record may declare a proposed_status above its claimed one. That is how a subsystem documented to a higher bar waits for the owner to decide whether it has actually earned it: obligations are checked against the proposal, so the writing is held to the higher standard, while the status the documentation publishes stays conservative until a human agrees.

Parameters
[in]recordOne subsystem record.
Returns
Ordered tuple of obligation ids.

Definition at line 106 of file audit_subsystem_lifecycle.py.

106def required_obligations(record: dict) -> tuple:
107 """!
108 @brief The obligation ids a record owes.
109
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.
117 """
118 status = record.get("proposed_status") or record.get("status")
119 owed: list = []
120 if status in LADDER:
121 for rung in LADDER[: LADDER.index(status) + 1]:
122 owed.extend(LADDER_OBLIGATIONS[rung])
123 else:
124 if status in INHERITS_LADDER:
125 peak = record.get("peak_status")
126 if peak in LADDER:
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]
132 # A status may re-owe something a lower rung already required; keep it once.
133 return tuple(dict.fromkeys(owed))
134
135
Here is the caller graph for this function:

◆ check_satisfaction()

list audit_subsystem_lifecycle.check_satisfaction ( str  context,
str  key,
  spec,
dict  pages,
set  published,
bool  public 
)

Verify one obligation or concern is genuinely answered.

An answer is a documentation reference that resolves, or a stated reason for non-applicability, or a literal value where the obligation is a fact rather than prose. An empty or filler answer is a violation.

Parameters
[in]contextRecord id, for messages.
[in]keyObligation or concern id.
[in]specThe declared answer.
[in]pagesPage index from page_index().
[in]publishedIds of the pages the site publishes.
[in]publicWhether the subsystem is publicly visible.
Returns
List of violation strings.

Definition at line 136 of file audit_subsystem_lifecycle.py.

137 public: bool) -> list:
138 """!
139 @brief Verify one obligation or concern is genuinely answered.
140
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.
151 """
152 if not isinstance(spec, dict):
153 return [f"{context}: '{key}' must be an object, got {type(spec).__name__}"]
154 problems = []
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:
158 problems.append(
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"
161 )
162 return problems
163 if "value" in spec:
164 if not str(spec["value"]).strip():
165 problems.append(f"{context}: '{key}' declares an empty value")
166 return problems
167 page = spec.get("page")
168 if not page:
169 problems.append(
170 f"{context}: '{key}' is unsatisfied - give it a page reference, a value, or a "
171 f"reasoned not_applicable"
172 )
173 return problems
174 if page not in pages:
175 problems.append(f"{context}: '{key}' cites page '{page}', which does not exist")
176 return problems
177 anchor = spec.get("anchor")
178 if anchor and anchor not in pages[page]:
179 problems.append(
180 f"{context}: '{key}' cites anchor '{anchor}' on page '{page}', which does not "
181 f"define it"
182 )
183 if public and page not in published:
184 problems.append(
185 f"{context}: '{key}' cites '{page}', which is not a published page, but the "
186 f"subsystem is publicly visible"
187 )
188 return problems
189
190
Here is the caller graph for this function:

◆ validate()

list audit_subsystem_lifecycle.validate ( list  records,
dict  pages,
dict  families,
set  published 
)

Validate every subsystem record against the lifecycle contract.

Parameters
[in]recordsSubsystem records.
[in]pagesPage index from page_index().
[in]familiesCapability family metadata, keyed by family id.
[in]publishedIds of the pages the site publishes.
Returns
List of violation strings; empty means the contract holds.

Definition at line 191 of file audit_subsystem_lifecycle.py.

191def validate(records: list, pages: dict, families: dict, published: set) -> list:
192 """!
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.
199 """
200 problems: list = []
201 seen: set = set()
202 for record in records:
203 identifier = record.get("id")
204 if not identifier:
205 problems.append("a record declares no id")
206 continue
207 if identifier in seen:
208 problems.append(f"{identifier}: declared more than once")
209 seen.add(identifier)
210
211 unknown = set(record) - RECORD_KEYS
212 if unknown:
213 problems.append(f"{identifier}: unknown field(s) {sorted(unknown)}")
214
215 status = record.get("status")
216 if status not in VALID_STATUSES:
217 problems.append(
218 f"{identifier}: status {status!r} is not one of {list(VALID_STATUSES)}"
219 )
220 continue
221
222 visibility = record.get("visibility")
223 if visibility not in VALID_VISIBILITY:
224 problems.append(
225 f"{identifier}: visibility {visibility!r} is not one of "
226 f"{list(VALID_VISIBILITY)}"
227 )
228 continue
229 if status == "internal" and visibility != "internal":
230 problems.append(
231 f"{identifier}: status 'internal' contradicts visibility 'public'; a "
232 f"subsystem the user can reach is at least experimental"
233 )
234
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]:
239 problems.append(
240 f"{identifier}: {previous or 'a new record'} -> '{status}' is not a valid "
241 f"lifecycle transition (allowed: {sorted(TRANSITIONS[previous])})"
242 )
243
244 proposed = record.get("proposed_status")
245 if proposed is not None:
246 if proposed not in LADDER:
247 problems.append(
248 f"{identifier}: proposed_status {proposed!r} must name a rung of "
249 f"{list(LADDER)}"
250 )
251 elif status not in LADDER or LADDER.index(proposed) <= LADDER.index(status):
252 problems.append(
253 f"{identifier}: proposed_status '{proposed}' is not above the claimed "
254 f"status '{status}'; a proposal that is not a promotion is noise"
255 )
256 elif not record.get("promotion_rationale"):
257 problems.append(
258 f"{identifier}: proposes '{proposed}' but gives no promotion_rationale. "
259 f"Say what the owner is being asked to confirm"
260 )
261
262 if status in NEEDS_PEAK:
263 peak = record.get("peak_status")
264 if peak not in LADDER:
265 problems.append(
266 f"{identifier}: status '{status}' requires peak_status naming the highest "
267 f"rung it reached, one of {list(LADDER)}"
268 )
269 elif record.get("peak_status") is not None:
270 problems.append(
271 f"{identifier}: peak_status applies only to {list(NEEDS_PEAK)}, not '{status}'"
272 )
273
274 obligations = record.get("obligations") or {}
275 owed = required_obligations(record)
276 for key in owed:
277 if key not in obligations:
278 problems.append(
279 f"{identifier}: status '{status}' owes '{key}', which is not declared"
280 )
281 else:
282 problems.extend(
283 check_satisfaction(identifier, key, obligations[key], pages, published,
284 visibility == "public")
285 )
286 for key in sorted(set(obligations) - set(owed)):
287 problems.append(
288 f"{identifier}: declares obligation '{key}', which status '{status}' does not "
289 f"owe; remove it or claim the status that owes it"
290 )
291
292 concerns = record.get("concerns") or {}
293 for key in sorted(concerns):
294 if key not in VALID_CONCERNS:
295 problems.append(
296 f"{identifier}: concern '{key}' is not in the concern vocabulary of "
297 f"64_Documentation_Extension_Framework"
298 )
299 continue
300 problems.extend(
301 check_satisfaction(identifier, key, concerns[key], pages, published,
302 visibility == "public")
303 )
304
305 # A planned subsystem must not already be presented as working behavior.
306 for family_id in record.get("capability_families", []):
307 family = families.get(family_id)
308 if family is None:
309 problems.append(
310 f"{identifier}: cites capability family '{family_id}', which is not "
311 f"registered"
312 )
313 continue
314 if status != "planned":
315 continue
316 live = sorted(
317 name for name, meta in family.get("value_metadata", {}).items()
318 if (meta or {}).get("status") == "supported"
319 )
320 if live:
321 problems.append(
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"
325 )
326 return problems
327
328
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int audit_subsystem_lifecycle.main ( )

Report subsystem lifecycle violations.

Returns
Process status code.

Definition at line 329 of file audit_subsystem_lifecycle.py.

329def main() -> int:
330 """!
331 @brief Report subsystem lifecycle violations.
332 @return Process status code.
333 """
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"])
337 families = {
338 family["id"]: family
339 for family in json.loads(FAMILIES.read_text(encoding="utf-8"))["families"]
340 }
341 problems = validate(records, page_index(), families, published)
342 if problems:
343 print("Subsystem lifecycle violations:", file=sys.stderr)
344 for problem in problems:
345 print(f" {problem}", file=sys.stderr)
346 print(
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.",
350 file=sys.stderr,
351 )
352 return 1
353
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")]
359 if proposals:
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']}")
366 return 0
367
368
int main(int argc, char **argv)
Entry point for the postprocessor executable.
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ REPO_ROOT

audit_subsystem_lifecycle.REPO_ROOT = Path(__file__).resolve().parents[2]

Definition at line 12 of file audit_subsystem_lifecycle.py.

◆ RECORDS

str audit_subsystem_lifecycle.RECORDS = REPO_ROOT / "tests" / "tooling" / "subsystem_records.json"

Definition at line 13 of file audit_subsystem_lifecycle.py.

◆ PAGE_TYPES

str audit_subsystem_lifecycle.PAGE_TYPES = REPO_ROOT / "tests" / "tooling" / "page_types.json"

Definition at line 14 of file audit_subsystem_lifecycle.py.

◆ FAMILIES

str audit_subsystem_lifecycle.FAMILIES = REPO_ROOT / "tests" / "tooling" / "capability_families.json"

Definition at line 15 of file audit_subsystem_lifecycle.py.

◆ PAGE_DIRS

tuple audit_subsystem_lifecycle.PAGE_DIRS = ("docs/pages", "docs")

Definition at line 16 of file audit_subsystem_lifecycle.py.

◆ LADDER

tuple audit_subsystem_lifecycle.LADDER = ("planned", "internal", "experimental", "supported")

Definition at line 21 of file audit_subsystem_lifecycle.py.

◆ LADDER_OBLIGATIONS

dict audit_subsystem_lifecycle.LADDER_OBLIGATIONS
Initial value:
1= {
2 "planned": ("purpose", "intended_scope", "design_owner", "not_implemented_status"),
3 "internal": ("scope_boundary", "architecture_boundary", "dependencies",
4 "developer_entry_points"),
5 "experimental": ("configuration", "selection_guidance", "observability", "limitations",
6 "safe_use_boundaries"),
7 "supported": ("evidence", "lifecycle_and_restart", "operations", "troubleshooting",
8 "examples", "complete_reference"),
9}

Definition at line 23 of file audit_subsystem_lifecycle.py.

◆ TERMINAL_OBLIGATIONS

dict audit_subsystem_lifecycle.TERMINAL_OBLIGATIONS
Initial value:
1= {
2 "known-defective": ("defect_disclosure", "defect_scope_record", "safe_use_boundaries",
3 "limitations"),
4 "deprecated": ("migration_path", "replacement", "compatibility_period", "removal_policy"),
5 "removed": ("history_record", "rejection_behavior"),
6}

Definition at line 35 of file audit_subsystem_lifecycle.py.

◆ NON_INHERITED

tuple audit_subsystem_lifecycle.NON_INHERITED = ("not_implemented_status",)

Definition at line 43 of file audit_subsystem_lifecycle.py.

◆ NEEDS_PEAK

tuple audit_subsystem_lifecycle.NEEDS_PEAK = ("known-defective", "deprecated", "removed")

Definition at line 44 of file audit_subsystem_lifecycle.py.

◆ INHERITS_LADDER

tuple audit_subsystem_lifecycle.INHERITS_LADDER = ("known-defective", "deprecated")

Definition at line 46 of file audit_subsystem_lifecycle.py.

◆ VALID_STATUSES

audit_subsystem_lifecycle.VALID_STATUSES = tuple(LADDER) + tuple(TERMINAL_OBLIGATIONS)

Definition at line 48 of file audit_subsystem_lifecycle.py.

◆ TRANSITIONS

dict audit_subsystem_lifecycle.TRANSITIONS
Initial value:
1= {
2 None: set(VALID_STATUSES) - {"removed"},
3 "planned": {"planned", "internal", "experimental", "supported", "removed"},
4 "internal": {"internal", "experimental", "supported", "known-defective", "deprecated"},
5 "experimental": {"experimental", "supported", "known-defective", "deprecated"},
6 "supported": {"supported", "known-defective", "deprecated"},
7 "known-defective": {"known-defective", "experimental", "supported", "deprecated", "removed"},
8 "deprecated": {"deprecated", "removed"},
9 "removed": {"removed"},
10}

Definition at line 58 of file audit_subsystem_lifecycle.py.

◆ VALID_VISIBILITY

tuple audit_subsystem_lifecycle.VALID_VISIBILITY = ("internal", "public")

Definition at line 69 of file audit_subsystem_lifecycle.py.

◆ VALID_CONCERNS

tuple audit_subsystem_lifecycle.VALID_CONCERNS
Initial value:
1= (
2 "numerical_method", "user_selector", "units_and_nondimensionalization",
3 "artifact_topology", "persistent_restart_state", "determinism_and_reproducibility",
4 "mpi_distributed_execution", "external_service", "security_credentials",
5 "generated_artifact", "file_format", "destructive_scope", "backward_compatibility",
6 "scientific_verification",
7)

Definition at line 72 of file audit_subsystem_lifecycle.py.

◆ RECORD_KEYS

dict audit_subsystem_lifecycle.RECORD_KEYS
Initial value:
1= {"id", "title", "status", "visibility", "previous_status", "peak_status",
2 "proposed_status", "promotion_rationale", "capability_families",
3 "obligations", "concerns", "note"}

Definition at line 80 of file audit_subsystem_lifecycle.py.

◆ MIN_REASON_CHARS

int audit_subsystem_lifecycle.MIN_REASON_CHARS = 30

Definition at line 84 of file audit_subsystem_lifecycle.py.

◆ FILLER_REASONS

dict audit_subsystem_lifecycle.FILLER_REASONS = {"n/a", "na", "none", "not applicable", "no", "-", "tbd"}

Definition at line 85 of file audit_subsystem_lifecycle.py.