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.
Files changed (39) hide show
  1. package/dist/commands/aggregated-checks.js +4 -6
  2. package/dist/commands/check.d.ts.map +1 -1
  3. package/dist/commands/check.js +55 -30
  4. package/dist/commands/query.d.ts.map +1 -1
  5. package/dist/commands/query.js +46 -28
  6. package/dist/commands/sync.d.ts.map +1 -1
  7. package/dist/commands/sync.js +19 -26
  8. package/dist/diagnostics.d.ts.map +1 -1
  9. package/dist/diagnostics.js +0 -2
  10. package/dist/extractors/manifest.d.ts +2 -0
  11. package/dist/extractors/manifest.d.ts.map +1 -1
  12. package/dist/extractors/manifest.js +1 -0
  13. package/dist/extractors/markdown.d.ts.map +1 -1
  14. package/dist/extractors/markdown.js +9 -1
  15. package/dist/prolog.d.ts +2 -0
  16. package/dist/prolog.d.ts.map +1 -1
  17. package/dist/prolog.js +45 -12
  18. package/dist/public/extractors/symbols-coordinator.d.ts.map +1 -1
  19. package/dist/public/extractors/symbols-coordinator.js +1 -2
  20. package/dist/public/prolog/index.d.ts.map +1 -1
  21. package/dist/public/prolog/index.js +1 -2
  22. package/dist/public/schemas/entity.d.ts.map +1 -1
  23. package/dist/public/schemas/entity.js +1 -3
  24. package/dist/public/schemas/relationship.d.ts.map +1 -1
  25. package/dist/public/schemas/relationship.js +1 -3
  26. package/dist/traceability/git-staged.d.ts.map +1 -1
  27. package/dist/traceability/git-staged.js +33 -7
  28. package/dist/traceability/symbol-extract.d.ts +6 -1
  29. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  30. package/dist/traceability/symbol-extract.js +62 -34
  31. package/dist/traceability/temp-kb.d.ts.map +1 -1
  32. package/dist/traceability/temp-kb.js +4 -3
  33. package/dist/traceability/validate.d.ts.map +1 -1
  34. package/dist/traceability/validate.js +8 -7
  35. package/package.json +5 -1
  36. package/src/public/extractors/symbols-coordinator.ts +1 -2
  37. package/src/public/prolog/index.ts +1 -2
  38. package/src/public/schemas/entity.ts +1 -3
  39. 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,CAmJtE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE"}
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, content: body } = matter(content);
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;
@@ -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;YAYT,YAAY;IA0B1B,OAAO,CAAC,WAAW;IA8EnB,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"}
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 goalList = Array.isArray(goal)
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 === 1 ? goalList[0] : `(${goalList.join(", ")})`;
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)) -> (forall(member(Name=Value, Vars), (write(Name), write('='), write_term(Value, [quoted(true), max_depth(0)]), writeln('.'))), writeln('__KIBI_TRUE__.')) ; writeln('__KIBI_FALSE__.'))",
296
- kbPath ? "kb_save, kb_detach" : "true",
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":"AAmBA,OAAO,EACL,uBAAuB,EACvB,KAAK,mBAAmB,GACzB,MAAM,yCAAyC,CAAC"}
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":"AAmBA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/public/prolog/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,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 PrologProcess
17
+ */
19
18
  export { PrologProcess } from "../../prolog.js";
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/entity.ts"],"names":[],"mappings":"AAoBA,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgEjB,CAAC;AAEF,eAAe,YAAY,CAAC"}
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":"AAoBA,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCvB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
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;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAS5C;AAsCD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,UAAQ,GAChB,SAAS,EAAE,CAoBb;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAiB,GAAG,UAAU,EAAE,CA4FpE;AAED,eAAe,cAAc,CAAC"}
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
- return entries.map((entry) => {
21
- const cols = entry.split("\t");
22
- const status = cols[0];
23
- const parts = cols.slice(1);
24
- return { status, parts };
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) && !isEntityMarkdown(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 declare function extractSymbolsFromStagedFile(stagedFile: StagedFile): ExtractedSymbol[];
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;AA0DD,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,UAAU,GACrB,eAAe,EAAE,CAuLnB"}
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 ((m = regex.exec(text))) {
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 + "|" + stagedFile.path);
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 + "::staged", content, {
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
- "\n" +
90
- fn
91
- .getJsDocs()
92
- .map((d) => d.getFullText())
93
- .join("\n"));
94
- const id = resolveSymbolId(stagedFile.path, name);
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
- "\n" +
121
- cls
122
- .getJsDocs()
123
- .map((d) => d.getFullText())
124
- .join("\n"));
125
- const id = resolveSymbolId(stagedFile.path, name);
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
- // attempt to read manifest entries for explicit id (best-effort)
214
- // extractFromManifest expects a file path; if manifest not present it will throw — catch it
215
- const ents = extractFromManifest(filePath);
216
- for (const e of ents) {
217
- if (e.entity.title === name)
218
- return e.entity.id;
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;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAkBrE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}
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;AAgHD,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
+ {"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(v) {
1
+ function unquoteAtom(value) {
2
2
  // remove surrounding single quotes and unescape doubled quotes
3
- v = v.trim();
4
- if (v.startsWith("'") && v.endsWith("'")) {
5
- v = v.slice(1, -1).replace(/''/g, "'");
3
+ const trimmed = value.trim();
4
+ if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
5
+ return trimmed.slice(1, -1).replace(/''/g, "'");
6
6
  }
7
- return v;
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["Rows"] ?? "[]";
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.6",
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,7 +14,6 @@
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 PrologProcess
20
19
  export { PrologProcess } from "../../prolog.js";
@@ -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",