@@ -832,29 +832,91 @@ def _check_one_obligation(
832832 attempt_name : str ,
833833 obligation : ObligationBlock ,
834834 ) -> list [AssuranceCheck ]:
835- evidence_count = sum (
836- isinstance (child , EvidenceRequirementStatement ) for child in obligation .statements
837- )
838- falsification_count = sum (
839- isinstance (child , FalsifyIfStatement ) for child in obligation .statements
840- )
841- return [
835+ evidence_requirements = [
836+ child .artifact
837+ for child in obligation .statements
838+ if isinstance (child , EvidenceRequirementStatement )
839+ ]
840+ falsification_conditions = [
841+ child .condition
842+ for child in obligation .statements
843+ if isinstance (child , FalsifyIfStatement )
844+ ]
845+
846+ checks = [
842847 self ._obligation_presence_check (
843- count = evidence_count ,
848+ count = len ( evidence_requirements ) ,
844849 check_id = "cognition_contract.obligation_evidence" ,
845850 label = "evidence requirement" ,
846851 attempt = attempt_name ,
847852 obligation = obligation .identifier ,
848853 ),
849854 self ._obligation_presence_check (
850- count = falsification_count ,
855+ count = len ( falsification_conditions ) ,
851856 check_id = "cognition_contract.obligation_falsification" ,
852857 label = "falsification gate" ,
853858 attempt = attempt_name ,
854859 obligation = obligation .identifier ,
855860 ),
856861 ]
857862
863+ checks .extend (
864+ self ._check_canonical_falsification_gate (
865+ attempt_name = attempt_name ,
866+ obligation = obligation ,
867+ declared_conditions = falsification_conditions ,
868+ )
869+ )
870+ return checks
871+
872+ def _check_canonical_falsification_gate (
873+ self ,
874+ * ,
875+ attempt_name : str ,
876+ obligation : ObligationBlock ,
877+ declared_conditions : list [str ],
878+ ) -> list [AssuranceCheck ]:
879+ definition = get_cognition_obligation (obligation .identifier )
880+ if definition is None :
881+ return []
882+
883+ declared_set = set (declared_conditions )
884+ required_set = set (definition .falsification_conditions )
885+ matched = tuple (
886+ condition
887+ for condition in definition .falsification_conditions
888+ if condition in declared_set
889+ )
890+
891+ if matched :
892+ return [
893+ AssuranceCheck (
894+ "cognition_contract.obligation_canonical_falsification.present" ,
895+ "pass" ,
896+ f"Obligation `{ obligation .identifier } ` declares canonical falsification gate(s)." ,
897+ {
898+ "attempt" : attempt_name ,
899+ "obligation" : obligation .identifier ,
900+ "matched_conditions" : list (matched ),
901+ "canonical_conditions" : list (definition .falsification_conditions ),
902+ },
903+ )
904+ ]
905+
906+ return [
907+ AssuranceCheck (
908+ "cognition_contract.obligation_canonical_falsification.missing" ,
909+ "fail" ,
910+ f"Obligation `{ obligation .identifier } ` must include at least one canonical falsification gate." ,
911+ {
912+ "attempt" : attempt_name ,
913+ "obligation" : obligation .identifier ,
914+ "declared_conditions" : declared_conditions ,
915+ "canonical_conditions" : list (required_set ),
916+ },
917+ )
918+ ]
919+
858920 def _obligation_presence_check (
859921 self ,
860922 * ,
0 commit comments