kibi-core 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -5
- package/schema/entities.pl +9 -0
- package/schema/relationships.pl +2 -0
- package/schema/validation.pl +43 -3
- package/src/checks.pl +200 -5
- package/src/kb.pl +53 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kibi-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Core Prolog modules and RDF graph logic for Kibi",
|
|
6
6
|
"type": "module",
|
|
@@ -9,10 +9,7 @@
|
|
|
9
9
|
"bun": ">=1.0"
|
|
10
10
|
},
|
|
11
11
|
"main": "./src/kb.pl",
|
|
12
|
-
"files": [
|
|
13
|
-
"src/**/*.pl",
|
|
14
|
-
"schema/**/*.pl"
|
|
15
|
-
],
|
|
12
|
+
"files": ["src/**/*.pl", "schema/**/*.pl"],
|
|
16
13
|
"license": "AGPL-3.0-or-later",
|
|
17
14
|
"author": "Piotr Franczyk",
|
|
18
15
|
"repository": {
|
package/schema/entities.pl
CHANGED
|
@@ -47,6 +47,15 @@ entity_property(fact, closed_world, boolean).
|
|
|
47
47
|
entity_property(fact, valid_from, datetime).
|
|
48
48
|
entity_property(fact, valid_to, datetime).
|
|
49
49
|
entity_property(fact, canonical_key, string).
|
|
50
|
+
entity_property(fact, predicate_name, string).
|
|
51
|
+
entity_property(fact, predicate_namespace, string).
|
|
52
|
+
entity_property(fact, predicate_arity, integer).
|
|
53
|
+
entity_property(fact, argument_names, list).
|
|
54
|
+
entity_property(fact, argument_types, list).
|
|
55
|
+
entity_property(fact, argument_descriptions, list).
|
|
56
|
+
entity_property(fact, aliases, list).
|
|
57
|
+
entity_property(fact, examples, list).
|
|
58
|
+
entity_property(fact, predicate_args, list).
|
|
50
59
|
|
|
51
60
|
% Typed test verification fields - only valid for test entities
|
|
52
61
|
entity_property(test, verification_scope, atom).
|
package/schema/relationships.pl
CHANGED
|
@@ -18,6 +18,7 @@ relationship_type(relates_to).
|
|
|
18
18
|
relationship_type(supersedes).
|
|
19
19
|
relationship_type(constrains).
|
|
20
20
|
relationship_type(requires_property).
|
|
21
|
+
relationship_type(requires_predicate).
|
|
21
22
|
|
|
22
23
|
% valid_relationship(RelType, FromType, ToType).
|
|
23
24
|
valid_relationship(depends_on, req, req).
|
|
@@ -38,6 +39,7 @@ valid_relationship(publishes, symbol, event).
|
|
|
38
39
|
valid_relationship(consumes, symbol, event).
|
|
39
40
|
valid_relationship(constrains, req, fact).
|
|
40
41
|
valid_relationship(requires_property, req, fact).
|
|
42
|
+
valid_relationship(requires_predicate, req, fact).
|
|
41
43
|
|
|
42
44
|
%% supersedes(+NewAdrId, +OldAdrId)
|
|
43
45
|
%% NewAdrId is the decision that replaces OldAdrId.
|
package/schema/validation.pl
CHANGED
|
@@ -88,6 +88,15 @@ is_fact_only_field(closed_world).
|
|
|
88
88
|
is_fact_only_field(valid_from).
|
|
89
89
|
is_fact_only_field(valid_to).
|
|
90
90
|
is_fact_only_field(canonical_key).
|
|
91
|
+
is_fact_only_field(predicate_name).
|
|
92
|
+
is_fact_only_field(predicate_namespace).
|
|
93
|
+
is_fact_only_field(predicate_arity).
|
|
94
|
+
is_fact_only_field(argument_names).
|
|
95
|
+
is_fact_only_field(argument_types).
|
|
96
|
+
is_fact_only_field(argument_descriptions).
|
|
97
|
+
is_fact_only_field(aliases).
|
|
98
|
+
is_fact_only_field(examples).
|
|
99
|
+
is_fact_only_field(predicate_args).
|
|
91
100
|
|
|
92
101
|
% is_test_only_field(+Key) - true if Key is a test-specific field
|
|
93
102
|
is_test_only_field(verification_scope).
|
|
@@ -97,7 +106,7 @@ is_test_only_field(verification_perspective).
|
|
|
97
106
|
validate_fact_shape(subject, Props) :-
|
|
98
107
|
memberchk(subject_key=_Val, Props),
|
|
99
108
|
valid_optional_fact_enums(Props),
|
|
100
|
-
|
|
109
|
+
valid_strict_polarity_in_props(Props).
|
|
101
110
|
validate_fact_shape(property_value, Props) :-
|
|
102
111
|
memberchk(subject_key=_Subject, Props),
|
|
103
112
|
memberchk(property_key=_Property, Props),
|
|
@@ -108,7 +117,7 @@ validate_fact_shape(property_value, Props) :-
|
|
|
108
117
|
exactly_one_value_field(Props),
|
|
109
118
|
value_type_matches_field(VT, Props),
|
|
110
119
|
valid_optional_fact_enums(Props),
|
|
111
|
-
|
|
120
|
+
valid_strict_polarity_in_props(Props).
|
|
112
121
|
validate_fact_shape(observation, Props) :-
|
|
113
122
|
valid_optional_fact_enums(Props),
|
|
114
123
|
valid_polarity_in_props(Props).
|
|
@@ -116,9 +125,26 @@ validate_fact_shape(meta, Props) :-
|
|
|
116
125
|
% Meta facts are allowed but don't require full strict property tuple yet
|
|
117
126
|
valid_optional_fact_enums(Props),
|
|
118
127
|
valid_polarity_in_props(Props).
|
|
128
|
+
validate_fact_shape(predicate_schema, Props) :-
|
|
129
|
+
memberchk(predicate_name=_Name, Props),
|
|
130
|
+
memberchk(predicate_arity=Arity, Props),
|
|
131
|
+
Arity >= 1,
|
|
132
|
+
memberchk(argument_names=ArgumentNames, Props),
|
|
133
|
+
memberchk(argument_types=ArgumentTypes, Props),
|
|
134
|
+
same_length(ArgumentNames, ArgumentTypes),
|
|
135
|
+
length(ArgumentNames, Arity),
|
|
136
|
+
valid_optional_fact_enums(Props),
|
|
137
|
+
valid_polarity_in_props(Props).
|
|
138
|
+
validate_fact_shape(predicate, Props) :-
|
|
139
|
+
memberchk(predicate_name=_Name, Props),
|
|
140
|
+
memberchk(predicate_args=Args, Props),
|
|
141
|
+
Args \= [],
|
|
142
|
+
memberchk(canonical_key=_CanonicalKey, Props),
|
|
143
|
+
valid_optional_fact_enums(Props),
|
|
144
|
+
valid_predicate_polarity_in_props(Props).
|
|
119
145
|
validate_fact_shape(Kind, _Props) :-
|
|
120
146
|
% Unknown fact_kind values fail validation
|
|
121
|
-
\+ memberchk(Kind, [subject, property_value, observation, meta]),
|
|
147
|
+
\+ memberchk(Kind, [subject, property_value, observation, meta, predicate_schema, predicate]),
|
|
122
148
|
fail.
|
|
123
149
|
|
|
124
150
|
% valid_operator(+Op)
|
|
@@ -140,6 +166,12 @@ valid_value_type(bool).
|
|
|
140
166
|
valid_polarity_in_props(Props) :-
|
|
141
167
|
( memberchk(polarity=P, Props) -> valid_polarity(P) ; true ).
|
|
142
168
|
|
|
169
|
+
valid_strict_polarity_in_props(Props) :-
|
|
170
|
+
( memberchk(polarity=P, Props) -> valid_strict_polarity(P) ; true ).
|
|
171
|
+
|
|
172
|
+
valid_predicate_polarity_in_props(Props) :-
|
|
173
|
+
( memberchk(polarity=P, Props) -> valid_predicate_polarity(P) ; true ).
|
|
174
|
+
|
|
143
175
|
% valid_optional_fact_enums(+Props)
|
|
144
176
|
% Validates enum-typed fact fields whenever they are present
|
|
145
177
|
valid_optional_fact_enums(Props) :-
|
|
@@ -155,6 +187,14 @@ valid_optional_test_enums(Props) :-
|
|
|
155
187
|
% valid_polarity(+P)
|
|
156
188
|
valid_polarity(require).
|
|
157
189
|
valid_polarity(forbid).
|
|
190
|
+
valid_polarity(assert).
|
|
191
|
+
valid_polarity(deny).
|
|
192
|
+
|
|
193
|
+
valid_strict_polarity(require).
|
|
194
|
+
valid_strict_polarity(forbid).
|
|
195
|
+
|
|
196
|
+
valid_predicate_polarity(assert).
|
|
197
|
+
valid_predicate_polarity(deny).
|
|
158
198
|
|
|
159
199
|
% valid_verification_scope(+Scope)
|
|
160
200
|
valid_verification_scope(unit).
|
package/src/checks.pl
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
check_domain_contradictions/1, % Returns list of contradiction violations
|
|
17
17
|
check_strict_fact_shape/1, % Returns list of malformed strict fact violations
|
|
18
18
|
check_strict_req_fact_pairing/1,% Returns list of malformed strict req/fact pairing violations
|
|
19
|
+
check_strict_readiness/1, % Returns list of strict readiness audit violations
|
|
19
20
|
run_checks_json/0, % Entry point for JSON output
|
|
20
21
|
violation_id_text/2 % Extract text from entity ID term (exported for testing)
|
|
21
22
|
]).
|
|
@@ -32,7 +33,7 @@ required_fields([id, title, status, created_at, updated_at, source]).
|
|
|
32
33
|
% Relationship types to check for dangling references
|
|
33
34
|
all_relationship_types([
|
|
34
35
|
depends_on, verified_by, validates, specified_by,
|
|
35
|
-
constrains, requires_property, supersedes, relates_to
|
|
36
|
+
constrains, requires_property, requires_predicate, supersedes, relates_to
|
|
36
37
|
]).
|
|
37
38
|
|
|
38
39
|
%% check_all(-ViolationsDict)
|
|
@@ -50,6 +51,7 @@ check_all(ViolationsDict) :-
|
|
|
50
51
|
check_domain_contradictions(Contradictions),
|
|
51
52
|
check_strict_fact_shape(StrictFactShape),
|
|
52
53
|
check_strict_req_fact_pairing(StrictReqFactPairing),
|
|
54
|
+
check_strict_readiness(StrictReadiness),
|
|
53
55
|
ViolationsDict = _{
|
|
54
56
|
must_priority_coverage: MustPriority,
|
|
55
57
|
symbol_coverage: SymbolCoverage,
|
|
@@ -60,7 +62,8 @@ check_all(ViolationsDict) :-
|
|
|
60
62
|
deprecated_adr_no_successor: DeprecatedADRs,
|
|
61
63
|
domain_contradictions: Contradictions,
|
|
62
64
|
strict_fact_shape: StrictFactShape,
|
|
63
|
-
strict_req_fact_pairing: StrictReqFactPairing
|
|
65
|
+
strict_req_fact_pairing: StrictReqFactPairing,
|
|
66
|
+
strict_readiness: StrictReadiness
|
|
64
67
|
}.
|
|
65
68
|
|
|
66
69
|
%% check_must_priority_coverage(-Violations)
|
|
@@ -384,9 +387,25 @@ strict_fact_shape_violation(violation(
|
|
|
384
387
|
-> fail % Observation facts have no required fields beyond fact_kind
|
|
385
388
|
; Kind = meta
|
|
386
389
|
-> fail % Meta facts have no required fields beyond fact_kind
|
|
390
|
+
; Kind = predicate_schema
|
|
391
|
+
-> findall(Msg, predicate_schema_shape_error(Props, Msg), Errors),
|
|
392
|
+
( Errors = []
|
|
393
|
+
-> fail
|
|
394
|
+
; Errors = [First|_],
|
|
395
|
+
Description = First,
|
|
396
|
+
Suggestion = "Ensure predicate_schema facts have predicate_name, predicate_arity, argument_names, and argument_types with matching arity"
|
|
397
|
+
)
|
|
398
|
+
; Kind = predicate
|
|
399
|
+
-> findall(Msg, predicate_shape_error(Props, Msg), Errors),
|
|
400
|
+
( Errors = []
|
|
401
|
+
-> fail
|
|
402
|
+
; Errors = [First|_],
|
|
403
|
+
Description = First,
|
|
404
|
+
Suggestion = "Ensure predicate facts have predicate_name, non-empty predicate_args, canonical_key, and assert/deny polarity when present"
|
|
405
|
+
)
|
|
387
406
|
; % Unknown fact_kind - report as malformed
|
|
388
407
|
format(string(Description), "Unknown fact_kind: ~w", [Kind]),
|
|
389
|
-
Suggestion = "Use one of: subject, property_value, observation, meta"
|
|
408
|
+
Suggestion = "Use one of: subject, property_value, observation, meta, predicate_schema, predicate"
|
|
390
409
|
),
|
|
391
410
|
|
|
392
411
|
( memberchk(source=Source0, Props)
|
|
@@ -432,6 +451,68 @@ value_type_matches_field(int, Props) :- memberchk(value_int=_, Props), !.
|
|
|
432
451
|
value_type_matches_field(number, Props) :- memberchk(value_number=_, Props), !.
|
|
433
452
|
value_type_matches_field(bool, Props) :- memberchk(value_bool=_, Props), !.
|
|
434
453
|
|
|
454
|
+
predicate_schema_shape_error(Props, "Predicate schema fact missing required field: predicate_name") :-
|
|
455
|
+
\+ memberchk(predicate_name=_, Props).
|
|
456
|
+
predicate_schema_shape_error(Props, "Predicate schema fact missing required field: predicate_arity") :-
|
|
457
|
+
memberchk(predicate_name=_, Props),
|
|
458
|
+
\+ memberchk(predicate_arity=_, Props).
|
|
459
|
+
predicate_schema_shape_error(Props, "Predicate schema fact missing required field: argument_names") :-
|
|
460
|
+
memberchk(predicate_arity=_, Props),
|
|
461
|
+
\+ memberchk(argument_names=_, Props).
|
|
462
|
+
predicate_schema_shape_error(Props, "Predicate schema fact missing required field: argument_types") :-
|
|
463
|
+
memberchk(argument_names=_, Props),
|
|
464
|
+
\+ memberchk(argument_types=_, Props).
|
|
465
|
+
predicate_schema_shape_error(Props, "Predicate schema fact argument_names length must match predicate_arity") :-
|
|
466
|
+
memberchk(predicate_arity=RawArity, Props),
|
|
467
|
+
checks_normalize_integer(RawArity, Arity),
|
|
468
|
+
memberchk(argument_names=RawNames, Props),
|
|
469
|
+
checks_normalize_atom_list(RawNames, Names),
|
|
470
|
+
length(Names, Count),
|
|
471
|
+
Count =\= Arity.
|
|
472
|
+
predicate_schema_shape_error(Props, "Predicate schema fact argument_types length must match predicate_arity") :-
|
|
473
|
+
memberchk(predicate_arity=RawArity, Props),
|
|
474
|
+
checks_normalize_integer(RawArity, Arity),
|
|
475
|
+
memberchk(argument_types=RawTypes, Props),
|
|
476
|
+
checks_normalize_atom_list(RawTypes, Types),
|
|
477
|
+
length(Types, Count),
|
|
478
|
+
Count =\= Arity.
|
|
479
|
+
|
|
480
|
+
predicate_shape_error(Props, "Predicate fact missing required field: predicate_name") :-
|
|
481
|
+
\+ memberchk(predicate_name=_, Props).
|
|
482
|
+
predicate_shape_error(Props, "Predicate fact missing required field: predicate_args") :-
|
|
483
|
+
memberchk(predicate_name=_, Props),
|
|
484
|
+
\+ memberchk(predicate_args=_, Props).
|
|
485
|
+
predicate_shape_error(Props, "Predicate fact predicate_args must be non-empty") :-
|
|
486
|
+
memberchk(predicate_args=RawArgs, Props),
|
|
487
|
+
checks_normalize_atom_list(RawArgs, Args),
|
|
488
|
+
Args = [].
|
|
489
|
+
predicate_shape_error(Props, "Predicate fact missing required field: canonical_key") :-
|
|
490
|
+
memberchk(predicate_args=_, Props),
|
|
491
|
+
\+ memberchk(canonical_key=_, Props).
|
|
492
|
+
predicate_shape_error(Props, "Predicate fact polarity must be assert or deny") :-
|
|
493
|
+
memberchk(polarity=RawPolarity, Props),
|
|
494
|
+
normalize_term_atom(RawPolarity, Polarity),
|
|
495
|
+
\+ memberchk(Polarity, [assert, deny]).
|
|
496
|
+
|
|
497
|
+
checks_normalize_integer(Raw, Integer) :-
|
|
498
|
+
( Raw = ^^(Value, _Type)
|
|
499
|
+
-> checks_normalize_integer(Value, Integer)
|
|
500
|
+
; integer(Raw)
|
|
501
|
+
-> Integer = Raw
|
|
502
|
+
; atom(Raw)
|
|
503
|
+
-> atom_number(Raw, Integer)
|
|
504
|
+
; string(Raw)
|
|
505
|
+
-> number_string(Integer, Raw)
|
|
506
|
+
).
|
|
507
|
+
|
|
508
|
+
checks_normalize_atom_list(Raw, Atoms) :-
|
|
509
|
+
( Raw = ^^(Value, _Type)
|
|
510
|
+
-> checks_normalize_atom_list(Value, Atoms)
|
|
511
|
+
; is_list(Raw)
|
|
512
|
+
-> maplist(normalize_term_atom, Raw, Atoms)
|
|
513
|
+
; Atoms = []
|
|
514
|
+
).
|
|
515
|
+
|
|
435
516
|
%% check_domain_contradictions(-Violations)
|
|
436
517
|
% Finds all pairs of requirements with contradicting required properties.
|
|
437
518
|
check_domain_contradictions(Violations) :-
|
|
@@ -445,7 +526,7 @@ check_domain_contradictions(Violations) :-
|
|
|
445
526
|
),
|
|
446
527
|
( contradicting_reqs(ReqA, ReqB, Reason),
|
|
447
528
|
format(string(EntityId), "~w/~w", [ReqA, ReqB]),
|
|
448
|
-
Description
|
|
529
|
+
format(string(Description), "~w [strict-readiness: contradiction-ready]", [Reason])
|
|
449
530
|
),
|
|
450
531
|
Violations
|
|
451
532
|
).
|
|
@@ -582,6 +663,118 @@ strict_req_fact_pairing_kind_label(legacy, "a legacy fact without fact_kind").
|
|
|
582
663
|
strict_req_fact_pairing_kind_label(Kind, Label) :-
|
|
583
664
|
format(string(Label), "a fact_kind=~w fact", [Kind]).
|
|
584
665
|
|
|
666
|
+
%% check_strict_readiness(-Violations)
|
|
667
|
+
% Reports current strict-readiness levels for requirements that are still not
|
|
668
|
+
% contradiction-ready. Legacy and prose-only requirements remain audit-only and
|
|
669
|
+
% are intentionally not treated as contradictions.
|
|
670
|
+
check_strict_readiness(Violations) :-
|
|
671
|
+
findall(
|
|
672
|
+
Violation,
|
|
673
|
+
strict_readiness_violation(Violation),
|
|
674
|
+
Violations0
|
|
675
|
+
),
|
|
676
|
+
sort(Violations0, Violations).
|
|
677
|
+
|
|
678
|
+
strict_readiness_violation(violation(
|
|
679
|
+
'strict-readiness',
|
|
680
|
+
ReqId,
|
|
681
|
+
Description,
|
|
682
|
+
Suggestion,
|
|
683
|
+
Source
|
|
684
|
+
)) :-
|
|
685
|
+
strict_readiness_issue(ReqId, Description, Suggestion),
|
|
686
|
+
violation_source(ReqId, req, Source).
|
|
687
|
+
|
|
688
|
+
strict_readiness_issue(
|
|
689
|
+
ReqId,
|
|
690
|
+
"Strict readiness: not-ready (prose-only). Requirement has no fact links, so contradiction checks skip it.",
|
|
691
|
+
"Add a subject fact via constrains and a property_value fact via requires_property to model contradiction-safe semantics"
|
|
692
|
+
) :-
|
|
693
|
+
kb_entity(ReqId, req, _),
|
|
694
|
+
strict_readiness_level(ReqId, prose_only).
|
|
695
|
+
|
|
696
|
+
strict_readiness_issue(
|
|
697
|
+
ReqId,
|
|
698
|
+
"Strict readiness: not-ready (traceable). Requirement is linked to facts only through legacy or non-strict links, so contradiction checks skip it.",
|
|
699
|
+
"Replace prose or legacy fact links with a subject fact via constrains and a property_value fact via requires_property"
|
|
700
|
+
) :-
|
|
701
|
+
kb_entity(ReqId, req, _),
|
|
702
|
+
strict_readiness_level(ReqId, traceable).
|
|
703
|
+
|
|
704
|
+
strict_readiness_issue(
|
|
705
|
+
ReqId,
|
|
706
|
+
Description,
|
|
707
|
+
"Add a matching property_value fact via requires_property for the same subject_key"
|
|
708
|
+
) :-
|
|
709
|
+
kb_entity(ReqId, req, _),
|
|
710
|
+
strict_readiness_level(ReqId, has_subject),
|
|
711
|
+
strict_readiness_primary_subject(ReqId, SubjectFactId, SubjectKey),
|
|
712
|
+
format(
|
|
713
|
+
string(Description),
|
|
714
|
+
"Strict readiness: not-ready (has-subject). Requirement constrains ~w (~w) but has no matching strict requires_property fact, so contradiction checks skip it.",
|
|
715
|
+
[SubjectFactId, SubjectKey]
|
|
716
|
+
).
|
|
717
|
+
|
|
718
|
+
strict_readiness_issue(
|
|
719
|
+
ReqId,
|
|
720
|
+
"Strict readiness: not-ready (strict-ready). Requirement has strict subject and property facts but no contradiction-ready matched pair, so contradiction checks still skip it.",
|
|
721
|
+
"Align constrains and requires_property on the same subject_key, and keep the requirement current if it should participate in contradiction checks"
|
|
722
|
+
) :-
|
|
723
|
+
kb_entity(ReqId, req, _),
|
|
724
|
+
strict_readiness_level(ReqId, strict_ready).
|
|
725
|
+
|
|
726
|
+
strict_readiness_level(ReqId, contradiction_ready) :-
|
|
727
|
+
kb:current_req(ReqId),
|
|
728
|
+
kb:effective_req_property_fact(
|
|
729
|
+
ReqId,
|
|
730
|
+
_SubjectKey,
|
|
731
|
+
_FactId,
|
|
732
|
+
_PropertyKey,
|
|
733
|
+
_Operator,
|
|
734
|
+
_ValueType,
|
|
735
|
+
_Value,
|
|
736
|
+
_Unit,
|
|
737
|
+
_Scope,
|
|
738
|
+
_Polarity,
|
|
739
|
+
_ValidFrom,
|
|
740
|
+
_ValidTo
|
|
741
|
+
),
|
|
742
|
+
!.
|
|
743
|
+
strict_readiness_level(ReqId, strict_ready) :-
|
|
744
|
+
strict_readiness_has_strict_subject(ReqId),
|
|
745
|
+
strict_readiness_has_strict_property(ReqId),
|
|
746
|
+
!.
|
|
747
|
+
strict_readiness_level(ReqId, has_subject) :-
|
|
748
|
+
strict_readiness_has_strict_subject(ReqId),
|
|
749
|
+
!.
|
|
750
|
+
strict_readiness_level(ReqId, traceable) :-
|
|
751
|
+
strict_readiness_has_fact_link(ReqId),
|
|
752
|
+
!.
|
|
753
|
+
strict_readiness_level(_ReqId, prose_only).
|
|
754
|
+
|
|
755
|
+
strict_readiness_has_fact_link(ReqId) :-
|
|
756
|
+
kb_relationship(constrains, ReqId, FactId),
|
|
757
|
+
kb_entity(FactId, fact, _),
|
|
758
|
+
!.
|
|
759
|
+
strict_readiness_has_fact_link(ReqId) :-
|
|
760
|
+
kb_relationship(requires_property, ReqId, FactId),
|
|
761
|
+
kb_entity(FactId, fact, _),
|
|
762
|
+
!.
|
|
763
|
+
|
|
764
|
+
strict_readiness_has_strict_subject(ReqId) :-
|
|
765
|
+
strict_readiness_primary_subject(ReqId, _FactId, _SubjectKey),
|
|
766
|
+
!.
|
|
767
|
+
|
|
768
|
+
strict_readiness_primary_subject(ReqId, FactId, SubjectKey) :-
|
|
769
|
+
kb_relationship(constrains, ReqId, FactId),
|
|
770
|
+
strict_req_fact_pairing_fact_kind(FactId, subject),
|
|
771
|
+
kb:fact_subject_key(FactId, SubjectKey).
|
|
772
|
+
|
|
773
|
+
strict_readiness_has_strict_property(ReqId) :-
|
|
774
|
+
kb_relationship(requires_property, ReqId, FactId),
|
|
775
|
+
strict_req_fact_pairing_fact_kind(FactId, property_value),
|
|
776
|
+
!.
|
|
777
|
+
|
|
585
778
|
%% run_checks_json
|
|
586
779
|
% Entry point for JSON output. Prints all violations as JSON to stdout.
|
|
587
780
|
run_checks_json :-
|
|
@@ -630,6 +823,7 @@ check_all_with_options(ViolationsDict, RequireAdr) :-
|
|
|
630
823
|
check_domain_contradictions(Contradictions),
|
|
631
824
|
check_strict_fact_shape(StrictFactShape),
|
|
632
825
|
check_strict_req_fact_pairing(StrictReqFactPairing),
|
|
826
|
+
check_strict_readiness(StrictReadiness),
|
|
633
827
|
ViolationsDict = _{
|
|
634
828
|
must_priority_coverage: MustPriority,
|
|
635
829
|
symbol_coverage: SymbolCoverage,
|
|
@@ -640,7 +834,8 @@ check_all_with_options(ViolationsDict, RequireAdr) :-
|
|
|
640
834
|
deprecated_adr_no_successor: DeprecatedADRs,
|
|
641
835
|
domain_contradictions: Contradictions,
|
|
642
836
|
strict_fact_shape: StrictFactShape,
|
|
643
|
-
strict_req_fact_pairing: StrictReqFactPairing
|
|
837
|
+
strict_req_fact_pairing: StrictReqFactPairing,
|
|
838
|
+
strict_readiness: StrictReadiness
|
|
644
839
|
}.
|
|
645
840
|
|
|
646
841
|
%% violations_dict_to_json(+ViolationsDict, -JsonDict)
|
package/src/kb.pl
CHANGED
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
adr_chain/2,
|
|
40
40
|
deprecated_no_successor/1,
|
|
41
41
|
symbol_no_req_coverage/2,
|
|
42
|
+
predicate_schema/6,
|
|
43
|
+
predicate_fact/5,
|
|
42
44
|
contradicting_reqs/3,
|
|
43
45
|
check_req_contradiction/1,
|
|
44
46
|
normalize_term_atom/2,
|
|
@@ -962,6 +964,57 @@ fact_property_tuple(FactId, Subject, Property, Op, ValType, Value, Unit, Scope,
|
|
|
962
964
|
( memberchk(scope=ScopeRaw, Props) -> normalize_term_atom(ScopeRaw, Scope) ; Scope = '' ),
|
|
963
965
|
( memberchk(polarity=PolarityRaw, Props) -> normalize_term_atom(PolarityRaw, Polarity) ; Polarity = require ).
|
|
964
966
|
|
|
967
|
+
%% predicate_schema(+FactId, -Namespace, -Name, -Arity, -ArgumentNames, -ArgumentTypes)
|
|
968
|
+
% Read one project-local ontology predicate schema fact.
|
|
969
|
+
predicate_schema(FactId, Namespace, Name, Arity, ArgumentNames, ArgumentTypes) :-
|
|
970
|
+
kb_entity(FactId, fact, Props),
|
|
971
|
+
memberchk(fact_kind=KindRaw, Props),
|
|
972
|
+
normalize_term_atom(KindRaw, predicate_schema),
|
|
973
|
+
memberchk(predicate_name=NameRaw, Props),
|
|
974
|
+
normalize_term_atom(NameRaw, Name),
|
|
975
|
+
( memberchk(predicate_namespace=NamespaceRaw, Props) -> normalize_term_atom(NamespaceRaw, Namespace) ; Namespace = default ),
|
|
976
|
+
memberchk(predicate_arity=ArityRaw, Props),
|
|
977
|
+
normalize_term_integer(ArityRaw, Arity),
|
|
978
|
+
memberchk(argument_names=ArgumentNamesRaw, Props),
|
|
979
|
+
normalize_term_atom_list(ArgumentNamesRaw, ArgumentNames),
|
|
980
|
+
memberchk(argument_types=ArgumentTypesRaw, Props),
|
|
981
|
+
normalize_term_atom_list(ArgumentTypesRaw, ArgumentTypes).
|
|
982
|
+
|
|
983
|
+
%% predicate_fact(+FactId, -Namespace, -Name, -Args, -Polarity)
|
|
984
|
+
% Read one ground ontology predicate fact.
|
|
985
|
+
predicate_fact(FactId, Namespace, Name, Args, Polarity) :-
|
|
986
|
+
kb_entity(FactId, fact, Props),
|
|
987
|
+
memberchk(fact_kind=KindRaw, Props),
|
|
988
|
+
normalize_term_atom(KindRaw, predicate),
|
|
989
|
+
memberchk(predicate_name=NameRaw, Props),
|
|
990
|
+
normalize_term_atom(NameRaw, Name),
|
|
991
|
+
( memberchk(predicate_namespace=NamespaceRaw, Props) -> normalize_term_atom(NamespaceRaw, Namespace) ; Namespace = default ),
|
|
992
|
+
memberchk(predicate_args=ArgsRaw, Props),
|
|
993
|
+
normalize_term_atom_list(ArgsRaw, Args),
|
|
994
|
+
( memberchk(polarity=PolarityRaw, Props) -> normalize_term_atom(PolarityRaw, Polarity) ; Polarity = assert ).
|
|
995
|
+
|
|
996
|
+
normalize_term_atom_list(List, Atoms) :-
|
|
997
|
+
is_list(List),
|
|
998
|
+
!,
|
|
999
|
+
maplist(normalize_term_atom, List, Atoms).
|
|
1000
|
+
normalize_term_atom_list(Raw, Atoms) :-
|
|
1001
|
+
unwrap_rdf_value(Raw, Value),
|
|
1002
|
+
is_list(Value),
|
|
1003
|
+
!,
|
|
1004
|
+
maplist(normalize_term_atom, Value, Atoms).
|
|
1005
|
+
|
|
1006
|
+
normalize_term_integer(Raw, Integer) :-
|
|
1007
|
+
unwrap_rdf_value(Raw, Value),
|
|
1008
|
+
( integer(Value)
|
|
1009
|
+
-> Integer = Value
|
|
1010
|
+
; atom(Value)
|
|
1011
|
+
-> atom_number(Value, Integer)
|
|
1012
|
+
; string(Value)
|
|
1013
|
+
-> number_string(Integer, Value)
|
|
1014
|
+
; Value = ^^(Nested, _Type)
|
|
1015
|
+
-> normalize_term_integer(Nested, Integer)
|
|
1016
|
+
).
|
|
1017
|
+
|
|
965
1018
|
%% fact_valid_interval(+FactId, -ValidFrom, -ValidTo)
|
|
966
1019
|
% Extract optional validity bounds for property_value facts.
|
|
967
1020
|
fact_valid_interval(FactId, ValidFrom, ValidTo) :-
|