kibi-core 0.18.0 → 0.18.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-core",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "private": false,
5
5
  "description": "Core Prolog modules and RDF graph logic for Kibi",
6
6
  "type": "module",
@@ -19,6 +19,7 @@ known_rule('symbol-coverage').
19
19
  known_rule('symbol-traceability').
20
20
  known_rule('no-dangling-refs').
21
21
  known_rule('source-relationship-parity').
22
+ known_rule('branch-store-not-compiled').
22
23
  known_rule('source-path-dangling').
23
24
  known_rule('no-cycles').
24
25
  known_rule('required-fields').
@@ -66,6 +67,7 @@ rule_enforcement_class('symbol-coverage', canonical).
66
67
  rule_enforcement_class('symbol-traceability', canonical).
67
68
  rule_enforcement_class('no-dangling-refs', canonical).
68
69
  rule_enforcement_class('source-relationship-parity', canonical).
70
+ rule_enforcement_class('branch-store-not-compiled', canonical).
69
71
  rule_enforcement_class('source-path-dangling', canonical).
70
72
  rule_enforcement_class('no-cycles', canonical).
71
73
  rule_enforcement_class('required-fields', canonical).
@@ -113,6 +115,7 @@ rule_implementation('symbol-coverage', prolog).
113
115
  rule_implementation('symbol-traceability', prolog).
114
116
  rule_implementation('no-dangling-refs', prolog).
115
117
  rule_implementation('source-relationship-parity', typescript).
118
+ rule_implementation('branch-store-not-compiled', typescript).
116
119
  rule_implementation('source-path-dangling', typescript).
117
120
  rule_implementation('no-cycles', prolog).
118
121
  rule_implementation('required-fields', prolog).
@@ -230,6 +233,7 @@ rule_description('symbol-coverage', 'Production symbols need qualifying coverage
230
233
  rule_description('symbol-traceability', 'Production symbols must directly implement requirements for ownership; covered_by is coverage only and executable_for is test identity only').
231
234
  rule_description('no-dangling-refs', 'All relationship targets must exist in the KB').
232
235
  rule_description('source-relationship-parity', 'Authored Markdown and relationship-shard edges must exactly match the compiled KB').
236
+ rule_description('branch-store-not-compiled', 'The current branch\'s KB store must be compiled from the authored .kb/ sources; a missing or empty store is reported once, naming kibi sync, instead of every store-backed rule reading an empty KB').
233
237
  rule_description('source-path-dangling', 'An authored entity\'s source field must name an existing workspace path (a #anchor suffix is ignored), an existing entity id, or an http(s) URL; a missing source is allowed').
234
238
  rule_description('no-cycles', 'No circular dependency chains in requirements').
235
239
  rule_description('required-fields', 'All entities must have required fields').
@@ -363,7 +363,10 @@ implication_witness_violation(Witness, violation(
363
363
  % was minted as several facts so requirements about it never meet: more than
364
364
  % one active subject fact for the same subject_key, and more than one active
365
365
  % property_value fact stating the same claim: the same subject_key,
366
- % property_key, operator, typed value and unit. Facts that differ in operator
366
+ % property_key, operator, polarity (absent = require), typed value and unit.
367
+ % A `forbid` fact states the opposite of its `require` twin, so the pair is
368
+ % never one claim. Facts linked only by superseded or deprecated requirements
369
+ % are history, not live duplicates. Facts that differ in operator
367
370
  % (the two bounds of a range) or in value (two requirements bounding the same
368
371
  % property differently) are distinct claims, which domain-contradictions and
369
372
  % domain-implication compare. Each group is reported once, on its first fact
@@ -390,7 +393,8 @@ duplicate_subject_fact_violations(Violations) :-
390
393
  findall(
391
394
  SubjectKey-FactId,
392
395
  ( fact_subject_key_of_kind(FactId, subject, SubjectKey),
393
- active_fact(FactId)
396
+ active_fact(FactId),
397
+ identity_live_fact(FactId)
394
398
  ),
395
399
  Pairs0
396
400
  ),
@@ -423,15 +427,17 @@ duplicate_subject_fact_violations(Violations) :-
423
427
  %% duplicate_property_fact_violations(-Violations)
424
428
  duplicate_property_fact_violations(Violations) :-
425
429
  findall(
426
- key(SubjectKey, PropertyKey, Operator, Value)-FactId,
430
+ key(SubjectKey, PropertyKey, Operator, Polarity, Value)-FactId,
427
431
  ( fact_subject_key_of_kind(FactId, property_value, SubjectKey),
428
432
  kb_entity(FactId, fact, Props),
429
433
  memberchk(property_key=RawProperty, Props),
430
434
  normalize_term_atom(RawProperty, PropertyKey),
431
435
  memberchk(operator=RawOperator, Props),
432
436
  normalize_term_atom(RawOperator, Operator),
437
+ property_value_polarity(Props, Polarity),
433
438
  property_value_signature(Props, Value),
434
- active_fact(FactId)
439
+ active_fact(FactId),
440
+ identity_live_fact(FactId)
435
441
  ),
436
442
  Pairs0
437
443
  ),
@@ -444,20 +450,55 @@ duplicate_property_fact_violations(Violations) :-
444
450
  Description,
445
451
  "Link every requirement to one shared fact and remove the duplicates (kb_delete) once nothing links them",
446
452
  Source,
447
- _{subjectKey: SubjectKey, propertyKey: PropertyKey, operator: Operator, facts: FactIds}
453
+ _{subjectKey: SubjectKey, propertyKey: PropertyKey, operator: Operator, polarity: Polarity, facts: FactIds}
448
454
  ),
449
- ( member(key(SubjectKey, PropertyKey, Operator, _)-FactIds, Groups),
455
+ ( member(key(SubjectKey, PropertyKey, Operator, Polarity, _)-FactIds, Groups),
450
456
  FactIds = [FirstId, _|_],
451
457
  length(FactIds, Count),
452
458
  atomic_list_concat(FactIds, ', ', FactText),
453
459
  format(string(Description),
454
- "~w active property_value facts state the same claim on ~w ~w (operator ~w, same value) (~w), so one claim is minted as several facts",
455
- [Count, SubjectKey, PropertyKey, Operator, FactText]),
460
+ "~w active property_value facts state the same claim on ~w ~w (operator ~w, polarity ~w, same value) (~w), so one claim is minted as several facts",
461
+ [Count, SubjectKey, PropertyKey, Operator, Polarity, FactText]),
456
462
  entity_text(FirstId, fact, source, Source)
457
463
  ),
458
464
  Violations
459
465
  ).
460
466
 
467
+ %% property_value_polarity(+Props, -Polarity)
468
+ % The polarity of a property_value fact; an absent polarity means require.
469
+ % `forbid` states the opposite claim of `require` on the same tuple, so the
470
+ % two never count as one claim minted twice.
471
+ % implements REQ-kibi-subject-vocabulary
472
+ property_value_polarity(Props, Polarity) :-
473
+ ( memberchk(polarity=Raw, Props),
474
+ normalize_term_atom(Raw, Polarity0),
475
+ Polarity0 \== ''
476
+ -> Polarity = Polarity0
477
+ ; Polarity = require
478
+ ).
479
+
480
+ %% identity_live_fact(+FactId)
481
+ % A fact still carried by the current requirement set: no requirement links
482
+ % it (an orphan duplicate stays visible), or at least one current requirement
483
+ % links it. A fact linked only by superseded or deprecated requirements is
484
+ % history kept for the append-only supersedes chain, not a live duplicate.
485
+ % `closed` means done, not retired, so a closed requirement still counts.
486
+ % implements REQ-kibi-subject-vocabulary
487
+ identity_live_fact(FactId) :-
488
+ findall(
489
+ ReqId,
490
+ ( member(LinkType, [constrains, requires_property, requires_predicate, requires_rule]),
491
+ kb_relationship(LinkType, ReqId, FactId)
492
+ ),
493
+ Linkers
494
+ ),
495
+ ( Linkers == []
496
+ -> true
497
+ ; member(ReqId, Linkers),
498
+ kb:current_req(ReqId)
499
+ -> true
500
+ ).
501
+
461
502
  %% property_value_signature(+Props, -Signature)
462
503
  % The typed value and unit of a property_value fact, as Field-Value pairs in a
463
504
  % fixed field order, so two facts compare equal only when they store the same