kibi-cli 0.2.6 → 0.2.8
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/dist/commands/aggregated-checks.js +4 -6
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +55 -30
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +46 -28
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +19 -26
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +0 -2
- package/dist/extractors/manifest.d.ts +2 -0
- package/dist/extractors/manifest.d.ts.map +1 -1
- package/dist/extractors/manifest.js +1 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +9 -1
- package/dist/prolog.d.ts +2 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +45 -12
- package/dist/public/extractors/symbols-coordinator.d.ts.map +1 -1
- package/dist/public/extractors/symbols-coordinator.js +1 -2
- package/dist/public/prolog/index.d.ts.map +1 -1
- package/dist/public/prolog/index.js +1 -2
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +1 -3
- package/dist/public/schemas/relationship.d.ts.map +1 -1
- package/dist/public/schemas/relationship.js +1 -3
- package/dist/traceability/git-staged.d.ts.map +1 -1
- package/dist/traceability/git-staged.js +33 -7
- package/dist/traceability/symbol-extract.d.ts +6 -1
- package/dist/traceability/symbol-extract.d.ts.map +1 -1
- package/dist/traceability/symbol-extract.js +62 -34
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +4 -3
- package/dist/traceability/validate.d.ts.map +1 -1
- package/dist/traceability/validate.js +8 -7
- package/package.json +5 -1
- package/src/public/extractors/symbols-coordinator.ts +1 -2
- package/src/public/prolog/index.ts +1 -2
- package/src/public/schemas/entity.ts +1 -3
- package/src/public/schemas/relationship.ts +1 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,qBAAqB,EAAE,CAAC;CACxC;AAaD,qBAAa,gBAAiB,SAAQ,KAAK;IAOhC,QAAQ,EAAE,MAAM;IANlB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;gBAG5B,OAAO,EAAE,MAAM,EACR,QAAQ,EAAE,MAAM,EACvB,OAAO,CAAC,EAAE;QACR,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB;IASM,QAAQ;CAUlB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CA8CV;AAGD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,qBAAqB,EAAE,CAAC;CACxC;AAaD,qBAAa,gBAAiB,SAAQ,KAAK;IAOhC,QAAQ,EAAE,MAAM;IANlB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;gBAG5B,OAAO,EAAE,MAAM,EACR,QAAQ,EAAE,MAAM,EACvB,OAAO,CAAC,EAAE;QACR,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB;IASM,QAAQ;CAUlB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CA8CV;AAGD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA4JtE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE"}
|
|
@@ -101,7 +101,7 @@ export function extractFromMarkdown(filePath) {
|
|
|
101
101
|
throw new FrontmatterError(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`, filePath, { classification: "File Read Error" });
|
|
102
102
|
}
|
|
103
103
|
try {
|
|
104
|
-
const { data
|
|
104
|
+
const { data } = matter(content);
|
|
105
105
|
if (content.trim().startsWith("---")) {
|
|
106
106
|
const parts = content.split("---");
|
|
107
107
|
if (parts.length < 3) {
|
|
@@ -136,6 +136,14 @@ export function extractFromMarkdown(filePath) {
|
|
|
136
136
|
const relationships = [];
|
|
137
137
|
if (Array.isArray(data.links)) {
|
|
138
138
|
for (const link of data.links) {
|
|
139
|
+
if (typeof link === "string") {
|
|
140
|
+
relationships.push({
|
|
141
|
+
type: "relates_to",
|
|
142
|
+
from: id,
|
|
143
|
+
to: link,
|
|
144
|
+
});
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
139
147
|
if (link &&
|
|
140
148
|
typeof link === "object" &&
|
|
141
149
|
typeof link.type === "string" &&
|
package/dist/prolog.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export declare class PrologProcess {
|
|
|
25
25
|
query(goal: string | string[]): Promise<QueryResult>;
|
|
26
26
|
invalidateCache(): void;
|
|
27
27
|
private isCacheableGoal;
|
|
28
|
+
private isMutatingGoal;
|
|
29
|
+
private isExplicitSaveGoal;
|
|
28
30
|
private queryOneShot;
|
|
29
31
|
private execOneShot;
|
|
30
32
|
private normalizeGoal;
|
package/dist/prolog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prolog.d.ts","sourceRoot":"","sources":["../src/prolog.ts"],"names":[],"mappings":"AA4BA,wBAAgB,eAAe,IAAI,MAAM,CAsCxC;AACD,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,cAAc,CACyC;IAC/D,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,aAAa,CAA6B;gBAEtC,OAAO,GAAE,aAAkB;IAKjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAoCd,YAAY;IAyCpB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAuJ1D,eAAe,IAAI,IAAI;IAIvB,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"prolog.d.ts","sourceRoot":"","sources":["../src/prolog.ts"],"names":[],"mappings":"AA4BA,wBAAgB,eAAe,IAAI,MAAM,CAsCxC;AACD,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,cAAc,CACyC;IAC/D,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,aAAa,CAA6B;gBAEtC,OAAO,GAAE,aAAkB;IAKjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAoCd,YAAY;IAyCpB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAuJ1D,eAAe,IAAI,IAAI;IAIvB,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,kBAAkB;YAIZ,YAAY;IAkC1B,OAAO,CAAC,WAAW;IA8FnB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,cAAc;IA8BtB,SAAS,IAAI,OAAO;IAIpB,MAAM,IAAI,MAAM;IAIV,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CAyBjC"}
|
package/dist/prolog.js
CHANGED
|
@@ -73,7 +73,7 @@ export class PrologProcess {
|
|
|
73
73
|
const kbPath = resolveKbPlPath();
|
|
74
74
|
this.process = spawn(this.swiplPath, [
|
|
75
75
|
"-g",
|
|
76
|
-
`use_module('${kbPath}'), set_prolog_flag(answer_write_options, [max_depth(0), quoted(true)])`,
|
|
76
|
+
`use_module('${kbPath}'), use_module(library(semweb/rdf_db)), set_prolog_flag(answer_write_options, [max_depth(0), quoted(true)])`,
|
|
77
77
|
"--quiet",
|
|
78
78
|
]);
|
|
79
79
|
if (!this.process.stdout || !this.process.stderr || !this.process.stdin) {
|
|
@@ -256,6 +256,16 @@ export class PrologProcess {
|
|
|
256
256
|
trimmed.startsWith("kb_delete_") ||
|
|
257
257
|
trimmed.startsWith("kb_retract_"));
|
|
258
258
|
}
|
|
259
|
+
// implements REQ-009
|
|
260
|
+
isMutatingGoal(goal) {
|
|
261
|
+
return (goal.includes("kb_assert_") ||
|
|
262
|
+
goal.includes("kb_delete_") ||
|
|
263
|
+
goal.includes("kb_retract_"));
|
|
264
|
+
}
|
|
265
|
+
// implements REQ-009
|
|
266
|
+
isExplicitSaveGoal(goal) {
|
|
267
|
+
return goal.trim().startsWith("kb_save");
|
|
268
|
+
}
|
|
259
269
|
async queryOneShot(goal) {
|
|
260
270
|
if (Array.isArray(goal)) {
|
|
261
271
|
return this.execOneShot(goal, this.attachedKbPath);
|
|
@@ -269,6 +279,13 @@ export class PrologProcess {
|
|
|
269
279
|
}
|
|
270
280
|
const attachMatch = trimmedGoal.match(/^kb_attach\('(.+)'\)$/);
|
|
271
281
|
if (attachMatch) {
|
|
282
|
+
if (this.attachedKbPath !== null) {
|
|
283
|
+
return {
|
|
284
|
+
success: false,
|
|
285
|
+
bindings: {},
|
|
286
|
+
error: "KB already attached",
|
|
287
|
+
};
|
|
288
|
+
}
|
|
272
289
|
const attachResult = this.execOneShot(trimmedGoal, null);
|
|
273
290
|
if (attachResult.success) {
|
|
274
291
|
this.attachedKbPath = attachMatch[1];
|
|
@@ -278,11 +295,21 @@ export class PrologProcess {
|
|
|
278
295
|
return this.execOneShot(trimmedGoal, this.attachedKbPath);
|
|
279
296
|
}
|
|
280
297
|
execOneShot(goal, kbPath) {
|
|
281
|
-
const
|
|
298
|
+
const originalGoalList = Array.isArray(goal)
|
|
282
299
|
? goal.map((item) => this.normalizeGoal(item))
|
|
283
300
|
: [this.normalizeGoal(goal)];
|
|
301
|
+
const explicitSaveRequested = Array.isArray(goal)
|
|
302
|
+
? originalGoalList.some((item) => this.isExplicitSaveGoal(item))
|
|
303
|
+
: false;
|
|
304
|
+
const goalList = explicitSaveRequested
|
|
305
|
+
? originalGoalList.filter((item) => !this.isExplicitSaveGoal(item))
|
|
306
|
+
: originalGoalList;
|
|
284
307
|
const isBatch = goalList.length > 1;
|
|
285
|
-
const combinedGoal = goalList.length ===
|
|
308
|
+
const combinedGoal = goalList.length === 0
|
|
309
|
+
? "true"
|
|
310
|
+
: goalList.length === 1
|
|
311
|
+
? goalList[0]
|
|
312
|
+
: `(${goalList.join(", ")})`;
|
|
286
313
|
const kbModulePath = resolveKbPlPath();
|
|
287
314
|
const prologGoal = [
|
|
288
315
|
`use_module('${kbModulePath}')`,
|
|
@@ -292,8 +319,14 @@ export class PrologProcess {
|
|
|
292
319
|
"read_term_from_atom(GoalAtom, Goal, [variable_names(Vars)])",
|
|
293
320
|
kbPath ? "getenv('KIBI_KB_PATH', KBPath), kb_attach(KBPath)" : "true",
|
|
294
321
|
isBatch ? "WrappedGoal = rdf_transaction(Goal)" : "WrappedGoal = Goal",
|
|
295
|
-
"(catch(call(WrappedGoal), E, (print_message(error, E), fail)) ->
|
|
296
|
-
kbPath
|
|
322
|
+
"(catch(call(WrappedGoal), E, (print_message(error, E), fail)) -> QuerySucceeded = true ; QuerySucceeded = false)",
|
|
323
|
+
kbPath &&
|
|
324
|
+
(explicitSaveRequested ||
|
|
325
|
+
goalList.some((item) => this.isMutatingGoal(item)))
|
|
326
|
+
? "(QuerySucceeded == true -> kb_save ; true)"
|
|
327
|
+
: "true",
|
|
328
|
+
kbPath ? "kb_detach" : "true",
|
|
329
|
+
"(QuerySucceeded == true -> (forall(member(Name=Value, Vars), (write(Name), write('='), write_term(Value, [quoted(true), max_depth(0)]), writeln('.'))), writeln('__KIBI_TRUE__.')) ; writeln('__KIBI_FALSE__.'))",
|
|
297
330
|
].join(", ");
|
|
298
331
|
const result = spawnSync(this.swiplPath, ["-q", "-g", prologGoal, "-t", "halt"], {
|
|
299
332
|
encoding: "utf8",
|
|
@@ -313,6 +346,13 @@ export class PrologProcess {
|
|
|
313
346
|
}
|
|
314
347
|
const stdout = result.stdout ?? "";
|
|
315
348
|
const stderr = result.stderr ?? "";
|
|
349
|
+
if (stderr.includes("ERROR")) {
|
|
350
|
+
return {
|
|
351
|
+
success: false,
|
|
352
|
+
bindings: {},
|
|
353
|
+
error: this.translateError(stderr),
|
|
354
|
+
};
|
|
355
|
+
}
|
|
316
356
|
if (stdout.includes("__KIBI_TRUE__")) {
|
|
317
357
|
const clean = stdout
|
|
318
358
|
.split("\n")
|
|
@@ -323,13 +363,6 @@ export class PrologProcess {
|
|
|
323
363
|
bindings: this.extractBindings(clean),
|
|
324
364
|
};
|
|
325
365
|
}
|
|
326
|
-
if (stderr.includes("ERROR")) {
|
|
327
|
-
return {
|
|
328
|
-
success: false,
|
|
329
|
-
bindings: {},
|
|
330
|
-
error: this.translateError(stderr),
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
366
|
return {
|
|
334
367
|
success: false,
|
|
335
368
|
bindings: {},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbols-coordinator.d.ts","sourceRoot":"","sources":["../../../src/public/extractors/symbols-coordinator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"symbols-coordinator.d.ts","sourceRoot":"","sources":["../../../src/public/extractors/symbols-coordinator.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,uBAAuB,EACvB,KAAK,mBAAmB,GACzB,MAAM,yCAAyC,CAAC"}
|
|
@@ -14,6 +14,5 @@
|
|
|
14
14
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
18
|
-
// Public re-export of symbols coordinator
|
|
17
|
+
*/
|
|
19
18
|
export { enrichSymbolCoordinates, } from "../../extractors/symbols-coordinator.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/public/prolog/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/public/prolog/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/entity.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/entity.ts"],"names":[],"mappings":"AAkBA,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgEjB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -14,9 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
18
|
-
// Public export of entity schema
|
|
19
|
-
// Generated from entity.schema.json
|
|
17
|
+
*/
|
|
20
18
|
const entitySchema = {
|
|
21
19
|
$id: "entity.schema.json",
|
|
22
20
|
title: "Entity",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relationship.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/relationship.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"relationship.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/relationship.ts"],"names":[],"mappings":"AAkBA,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCvB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -14,9 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
18
|
-
// Public export of relationship schema
|
|
19
|
-
// Generated from relationship.schema.json
|
|
17
|
+
*/
|
|
20
18
|
const relationshipSchema = {
|
|
21
19
|
$id: "relationship.schema.json",
|
|
22
20
|
title: "Relationship",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-staged.d.ts","sourceRoot":"","sources":["../../src/traceability/git-staged.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,CAAC;AAalE;;GAEG;
|
|
1
|
+
{"version":3,"file":"git-staged.d.ts","sourceRoot":"","sources":["../../src/traceability/git-staged.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,CAAC;AAalE;;GAEG;AAEH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAwB5C;AAiDD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,UAAQ,GAChB,SAAS,EAAE,CAoBb;AAED;;GAEG;AAEH,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAiB,GAAG,UAAU,EAAE,CA6FpE;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -13,16 +13,28 @@ function runGit(cmd, exec) {
|
|
|
13
13
|
/**
|
|
14
14
|
* Parse null-separated name-status output from git
|
|
15
15
|
*/
|
|
16
|
+
// implements REQ-014
|
|
16
17
|
export function parseNameStatusNull(input) {
|
|
17
18
|
if (!input)
|
|
18
19
|
return [];
|
|
19
20
|
const entries = input.split("\0").filter(Boolean);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const rows = [];
|
|
22
|
+
for (let i = 0; i < entries.length;) {
|
|
23
|
+
const entry = entries[i] ?? "";
|
|
24
|
+
if (entry.includes("\t")) {
|
|
25
|
+
const cols = entry.split("\t");
|
|
26
|
+
rows.push({ status: cols[0] ?? "", parts: cols.slice(1) });
|
|
27
|
+
i += 1;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const status = entry;
|
|
31
|
+
const isRenameOrCopy = /^[RC]\d*$/.test(status);
|
|
32
|
+
const partCount = isRenameOrCopy ? 2 : 1;
|
|
33
|
+
const parts = entries.slice(i + 1, i + 1 + partCount);
|
|
34
|
+
rows.push({ status, parts });
|
|
35
|
+
i += 1 + partCount;
|
|
36
|
+
}
|
|
37
|
+
return rows;
|
|
26
38
|
}
|
|
27
39
|
const SUPPORTED_EXT = new Set([
|
|
28
40
|
".ts",
|
|
@@ -34,6 +46,7 @@ const SUPPORTED_EXT = new Set([
|
|
|
34
46
|
".mjs",
|
|
35
47
|
".cjs",
|
|
36
48
|
]);
|
|
49
|
+
const SUPPORTED_MANIFEST = new Set(["symbols.yaml", "symbols.yml"]);
|
|
37
50
|
const ENTITY_MARKDOWN_DIRS = ["/requirements/", "/scenarios/", "/tests/"];
|
|
38
51
|
function shouldLogTraceDebug() {
|
|
39
52
|
return Boolean(process.env.KIBI_TRACE || process.env.KIBI_DEBUG);
|
|
@@ -57,6 +70,16 @@ function isEntityMarkdown(p) {
|
|
|
57
70
|
}
|
|
58
71
|
return false;
|
|
59
72
|
}
|
|
73
|
+
function isManifestFile(p) {
|
|
74
|
+
const base = p.split(/[\/]/).pop();
|
|
75
|
+
if (!base)
|
|
76
|
+
return false;
|
|
77
|
+
for (const name of SUPPORTED_MANIFEST) {
|
|
78
|
+
if (base === name)
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
60
83
|
/**
|
|
61
84
|
* Parse unified diff hunks (new-file coordinates) from git diff output
|
|
62
85
|
*/
|
|
@@ -86,6 +109,7 @@ export function parseHunksFromDiff(diffText, isNewFile = false) {
|
|
|
86
109
|
/**
|
|
87
110
|
* Get staged files with statuses, hunks and content.
|
|
88
111
|
*/
|
|
112
|
+
// implements REQ-014
|
|
89
113
|
export function getStagedFiles(exec = execSync) {
|
|
90
114
|
// 1. get staged name-status -z
|
|
91
115
|
let nameStatus;
|
|
@@ -115,7 +139,9 @@ export function getStagedFiles(exec = execSync) {
|
|
|
115
139
|
path = entry.parts[1];
|
|
116
140
|
}
|
|
117
141
|
}
|
|
118
|
-
if (!hasSupportedExt(path) &&
|
|
142
|
+
if (!hasSupportedExt(path) &&
|
|
143
|
+
!isEntityMarkdown(path) &&
|
|
144
|
+
!isManifestFile(path)) {
|
|
119
145
|
if (shouldLogTraceDebug()) {
|
|
120
146
|
console.debug(`Skipping unsupported extension: ${path}`);
|
|
121
147
|
}
|
|
@@ -11,5 +11,10 @@ export interface ExtractedSymbol {
|
|
|
11
11
|
hunkRanges: HunkRange[];
|
|
12
12
|
reqLinks: string[];
|
|
13
13
|
}
|
|
14
|
-
export
|
|
14
|
+
export interface ManifestLookupEntry {
|
|
15
|
+
id: string;
|
|
16
|
+
links?: string[];
|
|
17
|
+
}
|
|
18
|
+
export type ManifestLookup = Map<string, ManifestLookupEntry>;
|
|
19
|
+
export declare function extractSymbolsFromStagedFile(stagedFile: StagedFile, manifestLookup?: ManifestLookup): ExtractedSymbol[];
|
|
15
20
|
//# sourceMappingURL=symbol-extract.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbol-extract.d.ts","sourceRoot":"","sources":["../../src/traceability/symbol-extract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7D,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"symbol-extract.d.ts","sourceRoot":"","sources":["../../src/traceability/symbol-extract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7D,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AA4D9D,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,cAAc,GAC9B,eAAe,EAAE,CA+MnB"}
|
|
@@ -28,7 +28,10 @@ function parseReqDirectives(text) {
|
|
|
28
28
|
const regex = new RegExp(`implements\\s*:?\\s*(${REQ_ID}(?:\\s*,\\s*${REQ_ID})*)\\s*$`, "gim");
|
|
29
29
|
const reqs = new Set();
|
|
30
30
|
let m;
|
|
31
|
-
while (
|
|
31
|
+
while (true) {
|
|
32
|
+
m = regex.exec(text);
|
|
33
|
+
if (!m)
|
|
34
|
+
break;
|
|
32
35
|
const list = m[1];
|
|
33
36
|
for (const part of list.split(/[,\s]+/)) {
|
|
34
37
|
const p = part.trim();
|
|
@@ -42,9 +45,9 @@ function parseReqDirectives(text) {
|
|
|
42
45
|
function rangesIntersect(aStart, aEnd, bStart, bEnd) {
|
|
43
46
|
return aStart <= bEnd && bStart <= aEnd;
|
|
44
47
|
}
|
|
45
|
-
export function extractSymbolsFromStagedFile(stagedFile) {
|
|
48
|
+
export function extractSymbolsFromStagedFile(stagedFile, manifestLookup) {
|
|
46
49
|
const content = stagedFile.content ?? "";
|
|
47
|
-
const sha = computeContentSha(content
|
|
50
|
+
const sha = computeContentSha(`${content}|${stagedFile.path}`);
|
|
48
51
|
// TTL cache lookup
|
|
49
52
|
const now = Date.now();
|
|
50
53
|
let cached = sourceFileCache.get(sha);
|
|
@@ -52,7 +55,7 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
52
55
|
// create or recreate SourceFile in project (in-memory)
|
|
53
56
|
try {
|
|
54
57
|
const scriptKind = chooseScriptKind(stagedFile.path);
|
|
55
|
-
const sf = project.createSourceFile(stagedFile.path
|
|
58
|
+
const sf = project.createSourceFile(`${stagedFile.path}::staged`, content, {
|
|
56
59
|
overwrite: true,
|
|
57
60
|
scriptKind,
|
|
58
61
|
});
|
|
@@ -85,13 +88,13 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
85
88
|
const start = nameNode ? nameNode.getStart() : fn.getStart();
|
|
86
89
|
const end = fn.getEnd();
|
|
87
90
|
const span = getSpan(start, end);
|
|
88
|
-
const reqLinks = parseReqDirectives(fn.getFullText()
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
91
|
+
const reqLinks = parseReqDirectives(`${fn.getFullText()}\n${fn
|
|
92
|
+
.getJsDocs()
|
|
93
|
+
.map((d) => d.getFullText())
|
|
94
|
+
.join("\n")}`);
|
|
95
|
+
const { id, reqLinks: manifestLinks } = resolveSymbolId(stagedFile.path, name, manifestLookup);
|
|
96
|
+
// Merge manifest links with inline directive links (manifest links as fallback)
|
|
97
|
+
const mergedReqLinks = reqLinks.length > 0 ? reqLinks : (manifestLinks ?? []);
|
|
95
98
|
results.push({
|
|
96
99
|
id,
|
|
97
100
|
name,
|
|
@@ -102,7 +105,7 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
102
105
|
endLine: span.endLine,
|
|
103
106
|
},
|
|
104
107
|
hunkRanges: intersectingHunks(span.startLine, span.endLine, stagedFile.hunkRanges),
|
|
105
|
-
reqLinks,
|
|
108
|
+
reqLinks: mergedReqLinks,
|
|
106
109
|
});
|
|
107
110
|
}
|
|
108
111
|
catch { }
|
|
@@ -116,13 +119,13 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
116
119
|
const start = cls.getNameNode()?.getStart() ?? cls.getStart();
|
|
117
120
|
const end = cls.getEnd();
|
|
118
121
|
const span = getSpan(start, end);
|
|
119
|
-
const reqLinks = parseReqDirectives(cls.getText()
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const
|
|
122
|
+
const reqLinks = parseReqDirectives(`${cls.getText()}\n${cls
|
|
123
|
+
.getJsDocs()
|
|
124
|
+
.map((d) => d.getFullText())
|
|
125
|
+
.join("\n")}`);
|
|
126
|
+
const { id, reqLinks: manifestLinks } = resolveSymbolId(stagedFile.path, name, manifestLookup);
|
|
127
|
+
// Merge manifest links with inline directive links (manifest links as fallback)
|
|
128
|
+
const mergedReqLinks = reqLinks.length > 0 ? reqLinks : (manifestLinks ?? []);
|
|
126
129
|
results.push({
|
|
127
130
|
id,
|
|
128
131
|
name,
|
|
@@ -133,7 +136,7 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
133
136
|
endLine: span.endLine,
|
|
134
137
|
},
|
|
135
138
|
hunkRanges: intersectingHunks(span.startLine, span.endLine, stagedFile.hunkRanges),
|
|
136
|
-
reqLinks,
|
|
139
|
+
reqLinks: mergedReqLinks,
|
|
137
140
|
});
|
|
138
141
|
}
|
|
139
142
|
catch { }
|
|
@@ -148,7 +151,9 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
148
151
|
const end = en.getEnd();
|
|
149
152
|
const span = getSpan(start, end);
|
|
150
153
|
const reqLinks = parseReqDirectives(en.getText());
|
|
151
|
-
const id = resolveSymbolId(stagedFile.path, name);
|
|
154
|
+
const { id, reqLinks: manifestLinks } = resolveSymbolId(stagedFile.path, name, manifestLookup);
|
|
155
|
+
// Merge manifest links with inline directive links (manifest links as fallback)
|
|
156
|
+
const mergedReqLinks = reqLinks.length > 0 ? reqLinks : (manifestLinks ?? []);
|
|
152
157
|
results.push({
|
|
153
158
|
id,
|
|
154
159
|
name,
|
|
@@ -159,7 +164,7 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
159
164
|
endLine: span.endLine,
|
|
160
165
|
},
|
|
161
166
|
hunkRanges: intersectingHunks(span.startLine, span.endLine, stagedFile.hunkRanges),
|
|
162
|
-
reqLinks,
|
|
167
|
+
reqLinks: mergedReqLinks,
|
|
163
168
|
});
|
|
164
169
|
}
|
|
165
170
|
catch { }
|
|
@@ -175,7 +180,9 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
175
180
|
const end = decl.getEnd();
|
|
176
181
|
const span = getSpan(start, end);
|
|
177
182
|
const reqLinks = parseReqDirectives(decl.getText());
|
|
178
|
-
const id = resolveSymbolId(stagedFile.path, name);
|
|
183
|
+
const { id, reqLinks: manifestLinks } = resolveSymbolId(stagedFile.path, name, manifestLookup);
|
|
184
|
+
// Merge manifest links with inline directive links (manifest links as fallback)
|
|
185
|
+
const mergedReqLinks = reqLinks.length > 0 ? reqLinks : (manifestLinks ?? []);
|
|
179
186
|
results.push({
|
|
180
187
|
id,
|
|
181
188
|
name,
|
|
@@ -186,7 +193,7 @@ export function extractSymbolsFromStagedFile(stagedFile) {
|
|
|
186
193
|
endLine: span.endLine,
|
|
187
194
|
},
|
|
188
195
|
hunkRanges: intersectingHunks(span.startLine, span.endLine, stagedFile.hunkRanges),
|
|
189
|
-
reqLinks,
|
|
196
|
+
reqLinks: mergedReqLinks,
|
|
190
197
|
});
|
|
191
198
|
}
|
|
192
199
|
catch { }
|
|
@@ -208,21 +215,42 @@ function intersectingHunks(startLine, endLine, hunks) {
|
|
|
208
215
|
}
|
|
209
216
|
return out;
|
|
210
217
|
}
|
|
211
|
-
function resolveSymbolId(filePath, name) {
|
|
218
|
+
function resolveSymbolId(filePath, name, manifestLookup) {
|
|
219
|
+
// First, check the provided manifest lookup if available
|
|
220
|
+
if (manifestLookup) {
|
|
221
|
+
// Normalize the source file path for consistent lookup
|
|
222
|
+
const normalizedSource = filePath.startsWith("/")
|
|
223
|
+
? filePath
|
|
224
|
+
: `${filePath}`;
|
|
225
|
+
const lookupKey = `${normalizedSource}:${name}`;
|
|
226
|
+
const entry = manifestLookup.get(lookupKey);
|
|
227
|
+
if (entry) {
|
|
228
|
+
return { id: entry.id, reqLinks: entry.links };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Fallback: attempt to read manifest entries from a local symbols.yaml (best-effort)
|
|
212
232
|
try {
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
233
|
+
// Try to find a symbols.yaml in the same directory as the file
|
|
234
|
+
const dir = filePath.substring(0, filePath.lastIndexOf("/"));
|
|
235
|
+
if (dir) {
|
|
236
|
+
const manifestPath = `${dir}/symbols.yaml`;
|
|
237
|
+
const ents = extractFromManifest(manifestPath);
|
|
238
|
+
for (const e of ents) {
|
|
239
|
+
if (e.entity.title === name) {
|
|
240
|
+
// Extract requirement links from relationships
|
|
241
|
+
const reqLinks = e.relationships
|
|
242
|
+
.filter((r) => r.type === "implements" && r.to.match(/^[A-Z][A-Z0-9\-_]*$/))
|
|
243
|
+
.map((r) => r.to);
|
|
244
|
+
return { id: e.entity.id, reqLinks };
|
|
245
|
+
}
|
|
246
|
+
}
|
|
219
247
|
}
|
|
220
248
|
}
|
|
221
249
|
catch {
|
|
222
|
-
// ignore
|
|
250
|
+
// ignore - no local manifest or parse error
|
|
223
251
|
}
|
|
224
|
-
// deterministic id: sha(file:path:name)
|
|
252
|
+
// Final fallback: deterministic id: sha(file:path:name)
|
|
225
253
|
const h = createHash("sha256");
|
|
226
254
|
h.update(`${filePath}:${name}`);
|
|
227
|
-
return h.digest("hex").slice(0, 16);
|
|
255
|
+
return { id: h.digest("hex").slice(0, 16) };
|
|
228
256
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temp-kb.d.ts","sourceRoot":"","sources":["../../src/traceability/temp-kb.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAmDD,iBAAe,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAe/D;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA2C7E;
|
|
1
|
+
{"version":3,"file":"temp-kb.d.ts","sourceRoot":"","sources":["../../src/traceability/temp-kb.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAmDD,iBAAe,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAe/D;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA2C7E;AAGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAkBrE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}
|
|
@@ -82,14 +82,15 @@ export async function createTempKb(baseKbPath) {
|
|
|
82
82
|
trace(`temporary KB ready at ${kbPath}`);
|
|
83
83
|
return ctx;
|
|
84
84
|
}
|
|
85
|
+
// implements REQ-014
|
|
85
86
|
export function createOverlayFacts(symbols) {
|
|
86
87
|
const lines = [];
|
|
87
88
|
for (const symbol of symbols) {
|
|
88
|
-
lines.push(`changed_symbol(${escapePrologAtom(symbol.id)}).`);
|
|
89
|
-
lines.push(`changed_symbol_loc(${escapePrologAtom(symbol.id)}, ${escapePrologAtom(symbol.location.file)}, ${symbol.location.startLine}, 0, ${escapePrologAtom(symbol.name)}).`);
|
|
89
|
+
lines.push(`kb:changed_symbol(${escapePrologAtom(symbol.id)}).`);
|
|
90
|
+
lines.push(`kb:changed_symbol_loc(${escapePrologAtom(symbol.id)}, ${escapePrologAtom(symbol.location.file)}, ${symbol.location.startLine}, 0, ${escapePrologAtom(symbol.name)}).`);
|
|
90
91
|
// Emit overlay facts for requirement links from code-comment directives.
|
|
91
92
|
for (const reqId of symbol.reqLinks) {
|
|
92
|
-
lines.push(`changed_symbol_req(${escapePrologAtom(symbol.id)}, ${escapePrologAtom(reqId)}).`);
|
|
93
|
+
lines.push(`kb:changed_symbol_req(${escapePrologAtom(symbol.id)}, ${escapePrologAtom(reqId)}).`);
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
return lines.join("\n");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/traceability/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/traceability/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAiHD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,SAAS,EAAE,CAAC,CAqCtB;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAiBhE"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
function unquoteAtom(
|
|
1
|
+
function unquoteAtom(value) {
|
|
2
2
|
// remove surrounding single quotes and unescape doubled quotes
|
|
3
|
-
|
|
4
|
-
if (
|
|
5
|
-
|
|
3
|
+
const trimmed = value.trim();
|
|
4
|
+
if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
5
|
+
return trimmed.slice(1, -1).replace(/''/g, "'");
|
|
6
6
|
}
|
|
7
|
-
return
|
|
7
|
+
return trimmed;
|
|
8
8
|
}
|
|
9
9
|
function splitTopLevelComma(s) {
|
|
10
10
|
const parts = [];
|
|
@@ -98,14 +98,15 @@ function parsePrologListOfLists(value) {
|
|
|
98
98
|
}
|
|
99
99
|
return out;
|
|
100
100
|
}
|
|
101
|
+
// implements REQ-014
|
|
101
102
|
export async function validateStagedSymbols(options) {
|
|
102
103
|
const { minLinks, prolog } = options;
|
|
103
|
-
const goal = `findall([Sym,Count,File,Line,Col,Name], changed_symbol_violation(Sym, ${minLinks}, Count, File, Line, Col, Name), Rows)`;
|
|
104
|
+
const goal = `findall([Sym,Count,File,Line,Col,Name], kb:changed_symbol_violation(Sym, ${minLinks}, Count, File, Line, Col, Name), Rows)`;
|
|
104
105
|
const res = await prolog.query(goal);
|
|
105
106
|
if (!res.success) {
|
|
106
107
|
throw new Error(`Prolog query failed: ${res.error || "unknown error"}`);
|
|
107
108
|
}
|
|
108
|
-
const rowsRaw = res.bindings
|
|
109
|
+
const rowsRaw = res.bindings.Rows ?? "[]";
|
|
109
110
|
const lists = parsePrologListOfLists(rowsRaw);
|
|
110
111
|
const violations = [];
|
|
111
112
|
for (const row of lists) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kibi-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Kibi CLI for knowledge base management",
|
|
6
6
|
"engines": {
|
|
@@ -71,6 +71,10 @@
|
|
|
71
71
|
"kibi-core": "^0.1.10",
|
|
72
72
|
"ts-morph": "^23.0.0"
|
|
73
73
|
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@types/node": "latest",
|
|
76
|
+
"typescript": "^5.7.0"
|
|
77
|
+
},
|
|
74
78
|
"license": "AGPL-3.0-or-later",
|
|
75
79
|
"author": "Piotr Franczyk",
|
|
76
80
|
"repository": {
|
|
@@ -14,9 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
17
|
+
*/
|
|
18
18
|
|
|
19
|
-
// Public re-export of symbols coordinator
|
|
20
19
|
export {
|
|
21
20
|
enrichSymbolCoordinates,
|
|
22
21
|
type ManifestSymbolEntry,
|
|
@@ -14,10 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
17
|
+
*/
|
|
18
18
|
|
|
19
|
-
// Public export of entity schema
|
|
20
|
-
// Generated from entity.schema.json
|
|
21
19
|
const entitySchema = {
|
|
22
20
|
$id: "entity.schema.json",
|
|
23
21
|
title: "Entity",
|