kibi-core 0.9.1 → 0.11.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 +6 -4
- package/schema/entities.pl +3 -0
- package/schema/relationships.pl +1 -0
- package/schema/validation.pl +1 -0
- package/src/checks.pl +123 -5
- package/src/discovery.pl +2 -1
- package/src/kb.pl +1087 -24
- package/src/logic_ir.pl +1 -1
- package/src/requirement_proof.pl +306 -49
- package/src/status.pl +161 -34
package/src/status.pl
CHANGED
|
@@ -19,12 +19,16 @@ status_meta_dict(StatusDict) :-
|
|
|
19
19
|
snapshot_id(SnapshotId),
|
|
20
20
|
synced_at(DataFile, SyncedAt),
|
|
21
21
|
freshness_state(DataFile, Dirty, SyncState),
|
|
22
|
+
stale_reasons(StaleReasons, StaleReasonCount, StaleReasonsTruncated),
|
|
22
23
|
StatusDict = _{
|
|
23
24
|
branch: Branch,
|
|
24
25
|
snapshotId: SnapshotId,
|
|
25
26
|
syncedAt: SyncedAt,
|
|
26
27
|
dirty: Dirty,
|
|
27
28
|
syncState: SyncState,
|
|
29
|
+
staleReasons: StaleReasons,
|
|
30
|
+
staleReasonCount: StaleReasonCount,
|
|
31
|
+
staleReasonsTruncated: StaleReasonsTruncated,
|
|
28
32
|
kbPath: KbPath,
|
|
29
33
|
lastSyncSource: persisted
|
|
30
34
|
}.
|
|
@@ -37,15 +41,33 @@ status_meta_dict(StatusDict) :-
|
|
|
37
41
|
syncedAt: null,
|
|
38
42
|
dirty: false,
|
|
39
43
|
syncState: unknown,
|
|
44
|
+
staleReasons: [],
|
|
45
|
+
staleReasonCount: 0,
|
|
46
|
+
staleReasonsTruncated: false,
|
|
40
47
|
kbPath: KbPath,
|
|
41
48
|
lastSyncSource: unknown
|
|
42
49
|
}.
|
|
43
50
|
|
|
51
|
+
attached_kb_info(Branch, KbPath, DataFile) :-
|
|
52
|
+
kb:kb_attached(KbPath),
|
|
53
|
+
branch_workspace_from_kb_path(KbPath, Branch, _WorkspaceRoot),
|
|
54
|
+
kb:kb_storage_mode(journaled),
|
|
55
|
+
!,
|
|
56
|
+
directory_file_path(KbPath, 'CURRENT', DataFile).
|
|
44
57
|
attached_kb_info(Branch, KbPath, DataFile) :-
|
|
45
58
|
kb:kb_attached(KbPath),
|
|
46
59
|
branch_workspace_from_kb_path(KbPath, Branch, _WorkspaceRoot),
|
|
47
60
|
directory_file_path(KbPath, 'kb.rdf', DataFile).
|
|
48
61
|
|
|
62
|
+
snapshot_id(SnapshotId) :-
|
|
63
|
+
kb:kb_attached_snapshot(journal_snapshot(_Generation, Sequence)),
|
|
64
|
+
Sequence =:= 0,
|
|
65
|
+
!,
|
|
66
|
+
SnapshotId = missing.
|
|
67
|
+
snapshot_id(SnapshotId) :-
|
|
68
|
+
kb:kb_attached_snapshot(journal_snapshot(Generation, Sequence)),
|
|
69
|
+
!,
|
|
70
|
+
format(atom(SnapshotId), '~w:~w', [Generation, Sequence]).
|
|
49
71
|
snapshot_id(SnapshotId) :-
|
|
50
72
|
kb:kb_attached_snapshot(stamp(MTime, Size)),
|
|
51
73
|
!,
|
|
@@ -56,6 +78,14 @@ snapshot_id(SnapshotId) :-
|
|
|
56
78
|
SnapshotId = missing.
|
|
57
79
|
snapshot_id(unknown).
|
|
58
80
|
|
|
81
|
+
journal_before_first_commit :-
|
|
82
|
+
kb:kb_storage_mode(journaled),
|
|
83
|
+
kb:kb_attached_snapshot(journal_snapshot(_, 0)),
|
|
84
|
+
!.
|
|
85
|
+
|
|
86
|
+
synced_at(_, null) :-
|
|
87
|
+
journal_before_first_commit,
|
|
88
|
+
!.
|
|
59
89
|
synced_at(DataFile, SyncedAt) :-
|
|
60
90
|
exists_file(DataFile),
|
|
61
91
|
!,
|
|
@@ -64,6 +94,13 @@ synced_at(DataFile, SyncedAt) :-
|
|
|
64
94
|
% Before the first successful sync there is no kb.rdf, so the public JSON contract must expose syncedAt: null.
|
|
65
95
|
synced_at(_, null).
|
|
66
96
|
|
|
97
|
+
journal_before_first_commit_state(true, unknown) :-
|
|
98
|
+
journal_before_first_commit,
|
|
99
|
+
!.
|
|
100
|
+
|
|
101
|
+
freshness_state(_, Dirty, State) :-
|
|
102
|
+
journal_before_first_commit_state(Dirty, State),
|
|
103
|
+
!.
|
|
67
104
|
freshness_state(DataFile, true, stale) :-
|
|
68
105
|
exists_file(DataFile),
|
|
69
106
|
time_file(DataFile, SnapshotTime),
|
|
@@ -74,31 +111,118 @@ freshness_state(DataFile, false, fresh) :-
|
|
|
74
111
|
!.
|
|
75
112
|
freshness_state(_, true, unknown).
|
|
76
113
|
|
|
114
|
+
stale_reasons(Reasons, Count, Truncated) :-
|
|
115
|
+
findall(Reason, stale_indexed_source_reason(Reason), IndexedReasons),
|
|
116
|
+
findall(Reason, stale_knowledge_lane_reason(Reason), KnowledgeReasons),
|
|
117
|
+
findall(Reason, stale_documentation_reason(Reason), DocumentationReasons),
|
|
118
|
+
append(IndexedReasons, KnowledgeReasons, IndexedAndKnowledge),
|
|
119
|
+
append(IndexedAndKnowledge, DocumentationReasons, Reasons0),
|
|
120
|
+
sort(Reasons0, Sorted),
|
|
121
|
+
length(Sorted, Count),
|
|
122
|
+
( Count > 200
|
|
123
|
+
-> length(Reasons, 200), append(Reasons, _, Sorted), Truncated = true
|
|
124
|
+
; Reasons = Sorted, Truncated = false
|
|
125
|
+
).
|
|
126
|
+
|
|
127
|
+
stale_indexed_source_reason(Reason) :-
|
|
128
|
+
attached_workspace_root(WorkspaceRoot),
|
|
129
|
+
kb:kb_indexed_sources(Sources),
|
|
130
|
+
member(SourceAtom, Sources),
|
|
131
|
+
repo_relative_source(SourceAtom, RelativeSource),
|
|
132
|
+
directory_file_path(WorkspaceRoot, RelativeSource, SourcePath),
|
|
133
|
+
( exists_file(SourcePath)
|
|
134
|
+
-> time_file(SourcePath, FileTime),
|
|
135
|
+
kb_snapshot_time(SnapshotTime),
|
|
136
|
+
FileTime > SnapshotTime,
|
|
137
|
+
Code = indexed_source_newer
|
|
138
|
+
; exists_directory(SourcePath)
|
|
139
|
+
-> fail
|
|
140
|
+
; Code = indexed_source_missing
|
|
141
|
+
),
|
|
142
|
+
entity_ids_for_source(RelativeSource, EntityIds),
|
|
143
|
+
Reason = _{code: Code, path: RelativeSource, entityIds: EntityIds}.
|
|
144
|
+
|
|
145
|
+
stale_knowledge_lane_reason(Reason) :-
|
|
146
|
+
attached_workspace_root(WorkspaceRoot),
|
|
147
|
+
knowledge_lane(Lane),
|
|
148
|
+
directory_file_path(WorkspaceRoot, '.kb', KbRoot),
|
|
149
|
+
directory_file_path(KbRoot, Lane, LaneRoot),
|
|
150
|
+
exists_directory(LaneRoot),
|
|
151
|
+
kb_snapshot_time(SnapshotTime),
|
|
152
|
+
directory_tree_newer_path(LaneRoot, SnapshotTime, Path),
|
|
153
|
+
workspace_relative_path(WorkspaceRoot, Path, RelativePath),
|
|
154
|
+
entity_ids_for_source(RelativePath, EntityIds),
|
|
155
|
+
Reason = _{code: knowledge_source_newer, path: RelativePath, entityIds: EntityIds}.
|
|
156
|
+
|
|
157
|
+
stale_documentation_reason(Reason) :-
|
|
158
|
+
attached_workspace_root(WorkspaceRoot),
|
|
159
|
+
directory_file_path(WorkspaceRoot, 'documentation', DocumentationRoot),
|
|
160
|
+
exists_directory(DocumentationRoot),
|
|
161
|
+
kb_snapshot_time(SnapshotTime),
|
|
162
|
+
directory_tree_newer_path(DocumentationRoot, SnapshotTime, Path),
|
|
163
|
+
workspace_relative_path(WorkspaceRoot, Path, RelativePath),
|
|
164
|
+
entity_ids_for_source(RelativePath, EntityIds),
|
|
165
|
+
Reason = _{code: documentation_source_newer, path: RelativePath, entityIds: EntityIds}.
|
|
166
|
+
|
|
167
|
+
kb_snapshot_time(SnapshotTime) :-
|
|
168
|
+
kb:kb_attached(KbPath),
|
|
169
|
+
( directory_file_path(KbPath, 'CURRENT', DataFile), exists_file(DataFile)
|
|
170
|
+
-> time_file(DataFile, SnapshotTime)
|
|
171
|
+
; directory_file_path(KbPath, 'kb.rdf', DataFile), exists_file(DataFile)
|
|
172
|
+
-> time_file(DataFile, SnapshotTime)
|
|
173
|
+
; SnapshotTime = 0
|
|
174
|
+
).
|
|
175
|
+
|
|
176
|
+
entity_ids_for_source(RelativeSource, EntityIds) :-
|
|
177
|
+
findall(Id,
|
|
178
|
+
(kb_entity(Id, _Type, Props),
|
|
179
|
+
entity_source_property(Props, RawSource),
|
|
180
|
+
source_value_atom(RawSource, SourceAtom),
|
|
181
|
+
repo_relative_source(SourceAtom, RelativeSource),
|
|
182
|
+
Id \= '') ,
|
|
183
|
+
Ids0),
|
|
184
|
+
sort(Ids0, EntityIds).
|
|
185
|
+
|
|
186
|
+
entity_source_property(Props, RawSource) :-
|
|
187
|
+
memberchk(sourceFile=RawSource, Props),
|
|
188
|
+
!.
|
|
189
|
+
entity_source_property(Props, RawSource) :-
|
|
190
|
+
memberchk(source=RawSource, Props).
|
|
191
|
+
|
|
77
192
|
workspace_state_changed(SnapshotTime) :-
|
|
78
193
|
workspace_source_changed(SnapshotTime),
|
|
79
194
|
!.
|
|
195
|
+
workspace_state_changed(SnapshotTime) :-
|
|
196
|
+
knowledge_lane_tree_changed(SnapshotTime),
|
|
197
|
+
!.
|
|
80
198
|
workspace_state_changed(SnapshotTime) :-
|
|
81
199
|
documentation_tree_changed(SnapshotTime),
|
|
82
200
|
!.
|
|
83
201
|
|
|
84
202
|
workspace_source_changed(SnapshotTime) :-
|
|
85
203
|
attached_workspace_root(WorkspaceRoot),
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
source_value_atom(SourceValue, SourceAtom),
|
|
204
|
+
kb:kb_indexed_sources(Sources),
|
|
205
|
+
member(SourceAtom, Sources),
|
|
89
206
|
repo_relative_source(SourceAtom, RelativeSource),
|
|
90
207
|
directory_file_path(WorkspaceRoot, RelativeSource, SourcePath),
|
|
91
208
|
( exists_file(SourcePath)
|
|
92
209
|
-> time_file(SourcePath, FileTime),
|
|
93
210
|
FileTime > SnapshotTime
|
|
211
|
+
; exists_directory(SourcePath)
|
|
212
|
+
-> fail
|
|
94
213
|
; true
|
|
95
214
|
),
|
|
96
215
|
!.
|
|
97
216
|
|
|
98
|
-
|
|
217
|
+
knowledge_lane_tree_changed(SnapshotTime) :-
|
|
99
218
|
attached_workspace_root(WorkspaceRoot),
|
|
100
|
-
|
|
219
|
+
knowledge_lane(Lane),
|
|
220
|
+
directory_file_path(WorkspaceRoot, '.kb', KbRoot),
|
|
221
|
+
directory_file_path(KbRoot, Lane, LaneRoot),
|
|
222
|
+
exists_directory(LaneRoot),
|
|
223
|
+
directory_tree_newer(LaneRoot, SnapshotTime),
|
|
101
224
|
!.
|
|
225
|
+
|
|
102
226
|
documentation_tree_changed(SnapshotTime) :-
|
|
103
227
|
attached_workspace_root(WorkspaceRoot),
|
|
104
228
|
directory_file_path(WorkspaceRoot, 'documentation', DocumentationRoot),
|
|
@@ -106,55 +230,38 @@ documentation_tree_changed(SnapshotTime) :-
|
|
|
106
230
|
directory_tree_newer(DocumentationRoot, SnapshotTime),
|
|
107
231
|
!.
|
|
108
232
|
|
|
109
|
-
|
|
110
|
-
directory_file_path(WorkspaceRoot, 'documentation', DocumentationRoot),
|
|
111
|
-
exists_directory(DocumentationRoot),
|
|
112
|
-
documentation_markdown_file(DocumentationRoot, FilePath),
|
|
113
|
-
path_relative_to_workspace(WorkspaceRoot, FilePath, RelativePath),
|
|
114
|
-
\+ known_source_path(RelativePath),
|
|
115
|
-
!.
|
|
116
|
-
|
|
117
|
-
documentation_markdown_file(Path, Path) :-
|
|
233
|
+
directory_tree_newer(Path, SnapshotTime) :-
|
|
118
234
|
exists_file(Path),
|
|
119
|
-
file_name_extension(_, md, Path),
|
|
120
235
|
entity_documentation_file(Path),
|
|
121
236
|
\+ ignored_documentation_file(Path),
|
|
237
|
+
time_file(Path, EntryTime),
|
|
238
|
+
EntryTime > SnapshotTime,
|
|
122
239
|
!.
|
|
123
|
-
|
|
240
|
+
|
|
241
|
+
directory_tree_newer(Path, SnapshotTime) :-
|
|
124
242
|
exists_directory(Path),
|
|
125
243
|
directory_files(Path, Entries),
|
|
126
244
|
member(Entry, Entries),
|
|
127
245
|
Entry \= '.',
|
|
128
246
|
Entry \= '..',
|
|
129
247
|
directory_file_path(Path, Entry, ChildPath),
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
path_relative_to_workspace(WorkspaceRoot, FilePath, RelativePath) :-
|
|
133
|
-
atom_concat(WorkspaceRoot, '/', Prefix),
|
|
134
|
-
atom_concat(Prefix, RelativePath, FilePath).
|
|
135
|
-
|
|
136
|
-
known_source_path(RelativePath) :-
|
|
137
|
-
kb_entity(_, _, Props),
|
|
138
|
-
memberchk(source=SourceValue, Props),
|
|
139
|
-
source_value_atom(SourceValue, SourceAtom),
|
|
140
|
-
repo_relative_source(SourceAtom, RelativePath).
|
|
248
|
+
directory_tree_newer(ChildPath, SnapshotTime),
|
|
249
|
+
!.
|
|
141
250
|
|
|
142
|
-
|
|
251
|
+
directory_tree_newer_path(Path, SnapshotTime, Path) :-
|
|
143
252
|
exists_file(Path),
|
|
144
253
|
entity_documentation_file(Path),
|
|
145
254
|
\+ ignored_documentation_file(Path),
|
|
146
255
|
time_file(Path, EntryTime),
|
|
147
|
-
EntryTime > SnapshotTime
|
|
148
|
-
|
|
149
|
-
directory_tree_newer(Path, SnapshotTime) :-
|
|
256
|
+
EntryTime > SnapshotTime.
|
|
257
|
+
directory_tree_newer_path(Path, SnapshotTime, ChildPath) :-
|
|
150
258
|
exists_directory(Path),
|
|
151
259
|
directory_files(Path, Entries),
|
|
152
260
|
member(Entry, Entries),
|
|
153
261
|
Entry \= '.',
|
|
154
262
|
Entry \= '..',
|
|
155
|
-
directory_file_path(Path, Entry,
|
|
156
|
-
|
|
157
|
-
!.
|
|
263
|
+
directory_file_path(Path, Entry, Candidate),
|
|
264
|
+
directory_tree_newer_path(Candidate, SnapshotTime, ChildPath).
|
|
158
265
|
|
|
159
266
|
attached_workspace_root(WorkspaceRoot) :-
|
|
160
267
|
kb:kb_attached(KbPath),
|
|
@@ -180,12 +287,20 @@ branch_path_segments(KbPath, BranchesDir, Segments) :-
|
|
|
180
287
|
repo_relative_source(SourceAtom, RelativeSource) :-
|
|
181
288
|
strip_fragment(SourceAtom, NoFragment),
|
|
182
289
|
\+ sub_atom(NoFragment, _, _, _, '://'),
|
|
290
|
+
source_path_candidate(NoFragment),
|
|
183
291
|
( attached_workspace_root(WorkspaceRoot),
|
|
184
292
|
workspace_relative_path(WorkspaceRoot, NoFragment, RelativePath)
|
|
185
293
|
-> RelativeSource = RelativePath
|
|
186
294
|
; RelativeSource = NoFragment
|
|
187
295
|
).
|
|
188
296
|
|
|
297
|
+
source_path_candidate(Source) :-
|
|
298
|
+
sub_atom(Source, _, _, _, '/'),
|
|
299
|
+
!.
|
|
300
|
+
source_path_candidate(Source) :-
|
|
301
|
+
file_name_extension(_, Extension, Source),
|
|
302
|
+
Extension \= ''.
|
|
303
|
+
|
|
189
304
|
workspace_relative_path(WorkspaceRoot, SourcePath, RelativePath) :-
|
|
190
305
|
atom_concat(WorkspaceRoot, '/', Prefix),
|
|
191
306
|
atom_concat(Prefix, RelativePath, SourcePath).
|
|
@@ -217,8 +332,20 @@ source_value_atom(Val, Atom) :-
|
|
|
217
332
|
term_string(Val, Str),
|
|
218
333
|
atom_string(Atom, Str).
|
|
219
334
|
|
|
335
|
+
knowledge_lane(requirements).
|
|
336
|
+
knowledge_lane(scenarios).
|
|
337
|
+
knowledge_lane(tests).
|
|
338
|
+
knowledge_lane(facts).
|
|
339
|
+
knowledge_lane(adr).
|
|
340
|
+
knowledge_lane(flags).
|
|
341
|
+
knowledge_lane(events).
|
|
342
|
+
|
|
220
343
|
ignored_documentation_file(Path) :-
|
|
221
344
|
file_base_name(Path, 'README.md').
|
|
345
|
+
ignored_documentation_file(Path) :-
|
|
346
|
+
sub_atom(Path, _, _, _, '/tests/e2e/').
|
|
347
|
+
ignored_documentation_file(Path) :-
|
|
348
|
+
sub_atom(Path, _, _, _, '/tests/benchmarks/').
|
|
222
349
|
|
|
223
350
|
entity_documentation_file(Path) :-
|
|
224
351
|
read_file_to_string(Path, Content, []),
|