kibi-core 0.14.1 → 0.15.1
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/README.md +21 -0
- package/package.json +7 -2
- package/schema/entities.pl +22 -0
- package/schema/relationships.pl +14 -0
- package/schema/validation.pl +45 -1
- package/src/checks.pl +1850 -4
- package/src/discovery.pl +214 -3
- package/src/intervals.pl +175 -0
- package/src/kb.pl +87 -31
- package/src/logic_ir.pl +679 -65
- package/src/requirement_proof.pl +60 -6
- package/src/rule_registry.pl +77 -3
- package/src/semantic_quality.pl +151 -3
- package/src/status.pl +15 -1
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# kibi-core
|
|
2
|
+
|
|
3
|
+
The Prolog knowledge-base core of [Kibi](https://looted.github.io/kibi/): the entity and relationship schema, validation rules, inference, contradiction and proof checks that `kibi-cli` and `kibi-mcp` run against a repository's `.kb/` directory.
|
|
4
|
+
|
|
5
|
+
This package ships Prolog sources only (`src/kb.pl` is the entry module). You do not call it directly; install it with the CLI and MCP server:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev kibi-core kibi-cli kibi-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The [entity schema](https://looted.github.io/kibi/reference/entity-schema.html) and [inference rules](https://looted.github.io/kibi/reference/inference-rules.html) references describe what it encodes.
|
|
12
|
+
|
|
13
|
+
## Links
|
|
14
|
+
|
|
15
|
+
- [Documentation](https://looted.github.io/kibi/)
|
|
16
|
+
- [Source](https://github.com/Looted/kibi)
|
|
17
|
+
- [Issues](https://github.com/Looted/kibi/issues)
|
|
18
|
+
|
|
19
|
+
## License
|
|
20
|
+
|
|
21
|
+
AGPL-3.0-or-later
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kibi-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Core Prolog modules and RDF graph logic for Kibi",
|
|
6
6
|
"type": "module",
|
|
@@ -11,8 +11,13 @@
|
|
|
11
11
|
"files": ["src/**/*.pl", "schema/**/*.pl"],
|
|
12
12
|
"license": "AGPL-3.0-or-later",
|
|
13
13
|
"author": "Piotr Franczyk",
|
|
14
|
+
"homepage": "https://looted.github.io/kibi/",
|
|
14
15
|
"repository": {
|
|
15
16
|
"type": "git",
|
|
16
|
-
"url": "https://github.com/Looted/kibi.git"
|
|
17
|
+
"url": "https://github.com/Looted/kibi.git",
|
|
18
|
+
"directory": "packages/core"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/Looted/kibi/issues"
|
|
17
22
|
}
|
|
18
23
|
}
|
package/schema/entities.pl
CHANGED
|
@@ -30,6 +30,9 @@ entity_property(_, severity, atom).
|
|
|
30
30
|
entity_property(_, links, list).
|
|
31
31
|
entity_property(_, text_ref, uri).
|
|
32
32
|
entity_property(_, sourceFile, uri).
|
|
33
|
+
% Provenance of any authored entity: a JSON object (kind, ref, approved_by,
|
|
34
|
+
% recorded_at) naming who authored it and on what authority.
|
|
35
|
+
entity_property(_, origin, list_or_json).
|
|
33
36
|
entity_property(req, semantic_text, string).
|
|
34
37
|
entity_property(req, logic_claims, list).
|
|
35
38
|
entity_property(req, semantic_clauses, list).
|
|
@@ -39,6 +42,17 @@ entity_property(req, semantic_source_hash, string).
|
|
|
39
42
|
entity_property(req, semantic_inventory, list_or_json).
|
|
40
43
|
entity_property(req, proof_exempt, boolean).
|
|
41
44
|
entity_property(req, proof_exempt_reason, string).
|
|
45
|
+
% Human approval of an exception requirement (one that `exempts` another).
|
|
46
|
+
% Only an approved exception makes a success scenario feasible.
|
|
47
|
+
entity_property(req, approved_by, string).
|
|
48
|
+
entity_property(req, approval_ref, string).
|
|
49
|
+
% Why the requirement exists, in the words of whoever stated the intent.
|
|
50
|
+
% Explanation only: it is never part of the checked meaning.
|
|
51
|
+
entity_property(req, rationale, string).
|
|
52
|
+
% Claim keys of the exempted requirement an exception waives (all when absent).
|
|
53
|
+
entity_property(req, exempts_claims, list).
|
|
54
|
+
% Intended outcome of a scenario: success, rejection or error.
|
|
55
|
+
entity_property(scenario, expects, atom).
|
|
42
56
|
|
|
43
57
|
% Typed fact fields - only valid for fact entities
|
|
44
58
|
entity_property(fact, fact_kind, atom).
|
|
@@ -65,6 +79,9 @@ entity_property(fact, predicate_arity, integer).
|
|
|
65
79
|
entity_property(fact, argument_names, list).
|
|
66
80
|
entity_property(fact, argument_types, list).
|
|
67
81
|
entity_property(fact, argument_descriptions, list).
|
|
82
|
+
% Predicate-schema functional dependency: the named arguments determine the
|
|
83
|
+
% remaining ones, so two atoms with equal keys describe the same fact.
|
|
84
|
+
entity_property(fact, key_arguments, list).
|
|
68
85
|
% Predicate-schema vocabularies are JSON objects serialized as strings.
|
|
69
86
|
entity_property(fact, argument_constants, string).
|
|
70
87
|
entity_property(fact, argument_aliases, string).
|
|
@@ -112,6 +129,7 @@ optional_property(Type, priority) :- entity_type(Type).
|
|
|
112
129
|
optional_property(Type, severity) :- entity_type(Type).
|
|
113
130
|
optional_property(Type, links) :- entity_type(Type).
|
|
114
131
|
optional_property(Type, text_ref) :- entity_type(Type).
|
|
132
|
+
optional_property(Type, origin) :- entity_type(Type).
|
|
115
133
|
optional_property(req, semantic_text).
|
|
116
134
|
optional_property(req, logic_claims).
|
|
117
135
|
optional_property(req, semantic_clauses).
|
|
@@ -121,6 +139,10 @@ optional_property(req, semantic_source_hash).
|
|
|
121
139
|
optional_property(req, semantic_inventory).
|
|
122
140
|
optional_property(req, proof_exempt).
|
|
123
141
|
optional_property(req, proof_exempt_reason).
|
|
142
|
+
optional_property(req, approved_by).
|
|
143
|
+
optional_property(req, approval_ref).
|
|
144
|
+
optional_property(req, rationale).
|
|
145
|
+
optional_property(req, exempts_claims).
|
|
124
146
|
optional_property(test, verification_scope).
|
|
125
147
|
optional_property(test, verification_perspective).
|
|
126
148
|
optional_property(test, proof_contract).
|
package/schema/relationships.pl
CHANGED
|
@@ -22,6 +22,8 @@ relationship_type(constrains).
|
|
|
22
22
|
relationship_type(requires_property).
|
|
23
23
|
relationship_type(requires_predicate).
|
|
24
24
|
relationship_type(requires_rule).
|
|
25
|
+
relationship_type(assumes).
|
|
26
|
+
relationship_type(exempts).
|
|
25
27
|
|
|
26
28
|
% valid_relationship(RelType, FromType, ToType).
|
|
27
29
|
valid_relationship(depends_on, req, req).
|
|
@@ -45,6 +47,18 @@ valid_relationship(requires_property, req, fact).
|
|
|
45
47
|
valid_relationship(requires_predicate, req, fact).
|
|
46
48
|
valid_relationship(requires_rule, req, fact).
|
|
47
49
|
|
|
50
|
+
%% assumes(+ScenarioId, +FactId)
|
|
51
|
+
%% The scenario's outcome depends on the property_value fact holding (for
|
|
52
|
+
%% example "the order total is 0"). Checked against current requirements by
|
|
53
|
+
%% the scenario-feasibility rule.
|
|
54
|
+
% implements REQ-kibi-scenario-feasibility-v2
|
|
55
|
+
valid_relationship(assumes, scenario, fact).
|
|
56
|
+
|
|
57
|
+
%% exempts(+ExceptionReqId, +BaseReqId)
|
|
58
|
+
%% An approved exception requirement exempts the scenarios it specifies from
|
|
59
|
+
%% BaseReqId's property constraints. BaseReqId stays current and unchanged.
|
|
60
|
+
valid_relationship(exempts, req, req).
|
|
61
|
+
|
|
48
62
|
%% supersedes(+NewAdrId, +OldAdrId)
|
|
49
63
|
%% NewAdrId is the decision that replaces OldAdrId.
|
|
50
64
|
%% OldAdrId's status should be archived or deprecated as a consequence.
|
package/schema/validation.pl
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
:- use_module('entities.pl').
|
|
10
10
|
:- use_module('relationships.pl').
|
|
11
|
+
:- use_module(library(http/json)).
|
|
11
12
|
|
|
12
13
|
% validate_entity(+Type, +Props:list)
|
|
13
14
|
% Props is a list of Property=Value pairs (e.g. id=ID, title=Title)
|
|
@@ -19,7 +20,9 @@ validate_entity(Type, Props) :-
|
|
|
19
20
|
% all properties have correct types
|
|
20
21
|
forall(member(Key=Val, Props), validate_property_type(Type, Key, Val)),
|
|
21
22
|
% validate entity-specific shape constraints
|
|
22
|
-
validate_entity_shape(Type, Props)
|
|
23
|
+
validate_entity_shape(Type, Props),
|
|
24
|
+
% provenance, when present, names a known origin kind
|
|
25
|
+
valid_origin_in_props(Props).
|
|
23
26
|
|
|
24
27
|
% validate_relationship(+RelType, +From, +To)
|
|
25
28
|
% From and To are pairs Type=Id or structures type(Type) - allow Type or Type=Id
|
|
@@ -105,6 +108,7 @@ is_fact_only_field(predicate_arity).
|
|
|
105
108
|
is_fact_only_field(argument_names).
|
|
106
109
|
is_fact_only_field(argument_types).
|
|
107
110
|
is_fact_only_field(argument_descriptions).
|
|
111
|
+
is_fact_only_field(key_arguments).
|
|
108
112
|
is_fact_only_field(argument_constants).
|
|
109
113
|
is_fact_only_field(argument_aliases).
|
|
110
114
|
is_fact_only_field(aliases).
|
|
@@ -156,6 +160,7 @@ validate_fact_shape(predicate_schema, Props) :-
|
|
|
156
160
|
memberchk(argument_types=ArgumentTypes, Props),
|
|
157
161
|
same_length(ArgumentNames, ArgumentTypes),
|
|
158
162
|
length(ArgumentNames, Arity),
|
|
163
|
+
valid_key_arguments(Props, ArgumentNames),
|
|
159
164
|
valid_optional_fact_enums(Props),
|
|
160
165
|
valid_polarity_in_props(Props), !.
|
|
161
166
|
validate_fact_shape(predicate, Props) :-
|
|
@@ -185,6 +190,24 @@ validate_fact_shape(Kind, _Props) :-
|
|
|
185
190
|
\+ memberchk(Kind, [subject, property_value, observation, meta, predicate_schema, predicate, rule_schema, rule]),
|
|
186
191
|
fail.
|
|
187
192
|
|
|
193
|
+
% valid_key_arguments(+Props, +ArgumentNames)
|
|
194
|
+
% Optional key_arguments must be a non-empty list of distinct declared
|
|
195
|
+
% argument names.
|
|
196
|
+
valid_key_arguments(Props, ArgumentNames) :-
|
|
197
|
+
( memberchk(key_arguments=Keys, Props)
|
|
198
|
+
-> is_list(Keys),
|
|
199
|
+
Keys \= [],
|
|
200
|
+
maplist(text_atom, ArgumentNames, NameAtoms),
|
|
201
|
+
maplist(text_atom, Keys, KeyAtoms),
|
|
202
|
+
sort(KeyAtoms, UniqueKeys),
|
|
203
|
+
same_length(KeyAtoms, UniqueKeys),
|
|
204
|
+
forall(member(Key, KeyAtoms), memberchk(Key, NameAtoms))
|
|
205
|
+
; true
|
|
206
|
+
).
|
|
207
|
+
|
|
208
|
+
text_atom(Value, Atom) :- atom(Value), !, Atom = Value.
|
|
209
|
+
text_atom(Value, Atom) :- string(Value), atom_string(Atom, Value).
|
|
210
|
+
|
|
188
211
|
% valid_operator(+Op)
|
|
189
212
|
valid_operator(Op) :- memberchk(Op, [eq, neq, lt, lte, gt, gte]), !.
|
|
190
213
|
|
|
@@ -256,3 +279,24 @@ value_type_matches_field(string, Props) :- memberchk(value_string=_, Props), !.
|
|
|
256
279
|
value_type_matches_field(int, Props) :- memberchk(value_int=_, Props), !.
|
|
257
280
|
value_type_matches_field(number, Props) :- memberchk(value_number=_, Props), !.
|
|
258
281
|
value_type_matches_field(bool, Props) :- memberchk(value_bool=_, Props), !.
|
|
282
|
+
|
|
283
|
+
% valid_origin_in_props(+Props)
|
|
284
|
+
% Entity provenance travels as a JSON object string (or a dict). When present
|
|
285
|
+
% its kind must be human, agent, migration or import.
|
|
286
|
+
valid_origin_in_props(Props) :-
|
|
287
|
+
( memberchk(origin=Raw, Props)
|
|
288
|
+
-> origin_kind(Raw, Kind),
|
|
289
|
+
memberchk(Kind, [human, agent, migration, import])
|
|
290
|
+
; true
|
|
291
|
+
).
|
|
292
|
+
|
|
293
|
+
origin_kind(Raw, Kind) :-
|
|
294
|
+
( is_dict(Raw)
|
|
295
|
+
-> Dict = Raw
|
|
296
|
+
; (atom(Raw) ; string(Raw)),
|
|
297
|
+
catch(atom_json_dict(Raw, Dict, []), _, fail),
|
|
298
|
+
is_dict(Dict)
|
|
299
|
+
),
|
|
300
|
+
get_dict(kind, Dict, RawKind),
|
|
301
|
+
(atom(RawKind) ; string(RawKind)),
|
|
302
|
+
atom_string(Kind, RawKind).
|