Skills › Scientific Agent Skills › iso-standards-readiness › check_qmsr_transition.py
check_qmsr_transition.py
160 lines · skills/iso-standards-readiness/scripts/check_qmsr_transition.py at 5f2bc03
1#!/usr/bin/env python3
2"""Check documented evidence for the post-effective-date FDA QMSR transition."""
4from __future__ import annotations
6from typing import Any
8from _catalog import QMSR_TRANSITION_ITEMS
9from _common import (
10 Review,
11 finish,
12 guarded_main,
13 load_json,
14 require_root_object,
15 standard_parser,
16)
18ITEM_STATUSES = {
19 "not-started",
20 "in-progress",
21 "evidence-ready",
22 "not-applicable",
23}
26def validate(data: dict[str, Any]) -> tuple[Review, dict[str, int]]:
27 review = Review()
28 metadata = review.object(data.get("metadata"), "metadata")
29 if metadata is not None:
30 review.controlled_item(metadata, "metadata", require_approved=True)
31 review.text(metadata, "checklist_id", "metadata", max_chars=120)
32 review.date(metadata, "review_date", "metadata")
34 basis = review.object(data.get("qmsr_basis"), "qmsr_basis")
35 if basis is not None:
36 # The organization's source-review date is independent of this skill's
37 # research baseline. Currency itself requires controlled human review.
38 review.date(basis, "as_of", "qmsr_basis")
39 effective = review.date(basis, "effective_date", "qmsr_basis")
40 if effective != "2026-02-02":
41 review.add(
42 "EFFECTIVE_DATE",
43 "qmsr_basis.effective_date",
44 "current QMSR effective date must be recorded as 2026-02-02",
45 "blocker",
46 )
47 title = review.text(
48 basis,
49 "current_part_820_title",
50 "qmsr_basis",
51 max_chars=200,
52 )
53 if title != "Quality Management System Regulation":
54 review.add(
55 "CURRENT_TITLE",
56 "qmsr_basis.current_part_820_title",
57 "must identify current Part 820 as Quality Management System Regulation",
58 )
59 program = review.text(
60 basis,
61 "inspection_compliance_program",
62 "qmsr_basis",
63 max_chars=120,
64 )
65 if program != "7382.850":
66 review.add(
67 "INSPECTION_PROGRAM",
68 "qmsr_basis.inspection_compliance_program",
69 "must identify current FDA Compliance Program 7382.850",
70 )
71 review.text(basis, "owner", "qmsr_basis", max_chars=200)
72 review.evidence(basis, "qmsr_basis")
73 review.approval(basis, "qmsr_basis", require_approved=True)
74 review.source_refs(basis, "qmsr_basis", min_items=3)
76 items = review.list(data.get("items"), "items", min_items=1) or []
77 seen: set[str] = set()
78 ready = 0
79 for index, value in enumerate(items):
80 path = f"items[{index}]"
81 item = review.object(value, path)
82 if item is None:
83 continue
84 identifier = review.text(item, "id", path, max_chars=120)
85 if identifier:
86 seen.add(identifier)
87 if identifier not in QMSR_TRANSITION_ITEMS:
88 review.add(
89 "ITEM_UNKNOWN",
90 f"{path}.id",
91 "item is not in the versioned transition catalog",
92 )
93 review.text(item, "owner", path, max_chars=200)
94 status = review.choice(item, "status", ITEM_STATUSES, path)
95 review.text(item, "assessment", path, max_chars=3_000)
96 review.evidence(
97 item,
98 path,
99 min_items=1 if status in {"evidence-ready", "not-applicable"} else 0,
100 )
101 review.source_refs(item, path)
102 review.approval(
103 item,
104 path,
105 require_approved=status in {"evidence-ready", "not-applicable"},
106 )
107 if status == "evidence-ready":
108 ready += 1
109 if status == "not-applicable":
110 review.text(item, "rationale", path, max_chars=2_000)
111 review.unique_ids(items, "items")
113 missing = sorted(set(QMSR_TRANSITION_ITEMS) - seen)
114 for identifier in missing:
115 review.add(
116 "ITEM_MISSING",
117 "items",
118 f"missing transition evidence item: {identifier}",
119 )
121 attestations = review.object(data.get("attestations"), "attestations")
122 required_attestations = (
123 "iso_certificate_not_treated_as_fda_compliance",
124 "checklist_not_treated_as_compliance_determination",
125 "legacy_qsr_clause_map_not_used_as_current_requirements",
126 "applicability_decisions_owned_by_authorized_humans",
127 )
128 if attestations is not None:
129 for key in required_attestations:
130 if attestations.get(key) is not True:
131 review.add(
132 "ATTESTATION_REQUIRED",
133 f"attestations.{key}",
134 "must be explicitly true and supported by controlled evidence",
135 "blocker",
136 )
137 review.text(attestations, "owner", "attestations", max_chars=200)
138 review.evidence(attestations, "attestations")
139 review.approval(attestations, "attestations", require_approved=True)
141 return review, {
142 "catalog_items": len(QMSR_TRANSITION_ITEMS),
143 "evidence_ready": ready,
144 "items_submitted": len(items),
145 }
148def main() -> int:
149 parser = standard_parser(
150 "Check QMSR transition evidence using the current post-2026 Part 820 model.",
151 "Path to the local QMSR-transition JSON file",
152 )
153 args = parser.parse_args()
154 data = require_root_object(load_json(args.input))
155 review, metrics = validate(data)
156 return finish("check_qmsr_transition", review, args, metrics=metrics)
159if __name__ == "__main__":
160 guarded_main(main)