kibi-cli 0.5.1 → 0.6.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.
Files changed (78) hide show
  1. package/dist/commands/aggregated-checks.d.ts.map +1 -1
  2. package/dist/commands/aggregated-checks.js +3 -2
  3. package/dist/commands/check.d.ts.map +1 -1
  4. package/dist/commands/check.js +64 -53
  5. package/dist/commands/discovery-shared.d.ts +12 -5
  6. package/dist/commands/discovery-shared.d.ts.map +1 -1
  7. package/dist/commands/discovery-shared.js +21 -13
  8. package/dist/commands/doctor.js +9 -1
  9. package/dist/commands/init-helpers.d.ts.map +1 -1
  10. package/dist/commands/init-helpers.js +2 -3
  11. package/dist/commands/query.d.ts.map +1 -1
  12. package/dist/commands/query.js +15 -5
  13. package/dist/commands/search.js +1 -1
  14. package/dist/commands/sync/cache.d.ts +14 -4
  15. package/dist/commands/sync/cache.d.ts.map +1 -1
  16. package/dist/commands/sync/cache.js +36 -14
  17. package/dist/commands/sync/extraction.d.ts.map +1 -1
  18. package/dist/commands/sync/extraction.js +4 -9
  19. package/dist/commands/sync/manifest.d.ts +14 -3
  20. package/dist/commands/sync/manifest.d.ts.map +1 -1
  21. package/dist/commands/sync/manifest.js +29 -10
  22. package/dist/commands/sync/persistence.d.ts.map +1 -1
  23. package/dist/commands/sync/persistence.js +9 -5
  24. package/dist/commands/sync/staging.d.ts +19 -3
  25. package/dist/commands/sync/staging.d.ts.map +1 -1
  26. package/dist/commands/sync/staging.js +50 -27
  27. package/dist/commands/sync.d.ts.map +1 -1
  28. package/dist/commands/sync.js +16 -20
  29. package/dist/diagnostics.d.ts +1 -10
  30. package/dist/diagnostics.d.ts.map +1 -1
  31. package/dist/diagnostics.js +6 -12
  32. package/dist/env.d.ts +7 -0
  33. package/dist/env.d.ts.map +1 -0
  34. package/dist/env.js +41 -0
  35. package/dist/extractors/manifest.d.ts.map +1 -1
  36. package/dist/extractors/manifest.js +17 -15
  37. package/dist/extractors/markdown.d.ts +2 -0
  38. package/dist/extractors/markdown.d.ts.map +1 -1
  39. package/dist/extractors/markdown.js +124 -30
  40. package/dist/extractors/relationships.d.ts.map +1 -1
  41. package/dist/extractors/relationships.js +10 -4
  42. package/dist/extractors/symbols-coordinator.d.ts +5 -2
  43. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  44. package/dist/extractors/symbols-coordinator.js +5 -2
  45. package/dist/extractors/symbols-ts.d.ts.map +1 -1
  46. package/dist/extractors/symbols-ts.js +56 -10
  47. package/dist/prolog/codec.d.ts +0 -43
  48. package/dist/prolog/codec.d.ts.map +1 -1
  49. package/dist/prolog/codec.js +68 -74
  50. package/dist/prolog.d.ts.map +1 -1
  51. package/dist/prolog.js +39 -25
  52. package/dist/public/schemas/relationship.d.ts.map +1 -1
  53. package/dist/public/schemas/relationship.js +1 -0
  54. package/dist/query/service.d.ts +9 -0
  55. package/dist/query/service.d.ts.map +1 -1
  56. package/dist/query/service.js +27 -10
  57. package/dist/schemas/entity.schema.json +22 -0
  58. package/dist/search-ranking.d.ts.map +1 -1
  59. package/dist/search-ranking.js +19 -3
  60. package/dist/traceability/git-staged.d.ts.map +1 -1
  61. package/dist/traceability/git-staged.js +22 -6
  62. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  63. package/dist/traceability/symbol-extract.js +10 -4
  64. package/dist/traceability/temp-kb.d.ts +12 -0
  65. package/dist/traceability/temp-kb.d.ts.map +1 -1
  66. package/dist/traceability/temp-kb.js +42 -8
  67. package/dist/traceability/validate.d.ts.map +1 -1
  68. package/dist/traceability/validate.js +11 -2
  69. package/dist/utils/branch-resolver.d.ts +4 -0
  70. package/dist/utils/branch-resolver.d.ts.map +1 -1
  71. package/dist/utils/branch-resolver.js +29 -12
  72. package/dist/utils/config.d.ts.map +1 -1
  73. package/dist/utils/config.js +8 -2
  74. package/dist/utils/rule-registry.js +2 -2
  75. package/package.json +3 -9
  76. package/src/public/schemas/relationship.ts +1 -0
  77. package/src/schemas/entity.schema.json +22 -0
  78. package/src/schemas/relationship.schema.json +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"aggregated-checks.d.ts","sourceRoot":"","sources":["../../src/commands/aggregated-checks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,cAAc,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAU5C;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,EACrB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EAClC,UAAU,UAAQ,GACjB,OAAO,CAAC,SAAS,EAAE,CAAC,CA2DtB"}
1
+ {"version":3,"file":"aggregated-checks.d.ts","sourceRoot":"","sources":["../../src/commands/aggregated-checks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,cAAc,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAU5C;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,EACrB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EAClC,UAAU,UAAQ,GACjB,OAAO,CAAC,SAAS,EAAE,CAAC,CA4DtB"}
@@ -10,6 +10,7 @@ import { escapeAtom } from "../prolog/codec.js";
10
10
  * @param requireAdr - Whether to require ADR constraints for symbol-traceability
11
11
  */
12
12
  export async function runAggregatedChecks(prolog, rulesAllowlist, requireAdr = false) {
13
+ // implements REQ-003
13
14
  const violations = [];
14
15
  const checksPlPath = path.join(path.dirname(resolveKbPlPath()), "checks.pl");
15
16
  const checksPlPathEscaped = escapeAtom(checksPlPath);
@@ -48,8 +49,8 @@ export async function runAggregatedChecks(prolog, rulesAllowlist, requireAdr = f
48
49
  rule: v.rule,
49
50
  entityId: v.entityId,
50
51
  description: v.description,
51
- suggestion: v.suggestion || undefined,
52
- source: v.source || undefined,
52
+ ...(v.suggestion ? { suggestion: v.suggestion } : {}),
53
+ ...(v.source ? { source: v.source } : {}),
53
54
  });
54
55
  }
55
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAmDA,OAAO,EAGL,KAAK,SAAS,EAEf,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAI1B,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAmGD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgR/B"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAuDA,OAAO,EAGL,KAAK,SAAS,EAEf,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAI1B,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA+GD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgR/B"}
@@ -17,7 +17,8 @@
17
17
  */
18
18
  import { existsSync } from "node:fs";
19
19
  import * as path from "node:path";
20
- import { extractFromManifest, extractFromManifestString } from "../extractors/manifest.js";
20
+ import { getBranchOverride, isCliTraceOrDebugEnabled } from "../env.js";
21
+ import { extractFromManifest, extractFromManifestString, } from "../extractors/manifest.js";
21
22
  import { extractFromMarkdownString, } from "../extractors/markdown.js";
22
23
  import { PrologProcess } from "../prolog.js";
23
24
  import { escapeAtom, parseTriples, parseViolationRows, } from "../prolog/codec.js";
@@ -31,6 +32,10 @@ import { safeCleanupProlog } from "../utils/prolog-cleanup.js";
31
32
  import { RULES, getEffectiveRules, } from "../utils/rule-registry.js";
32
33
  import { runAggregatedChecks } from "./aggregated-checks.js";
33
34
  import { getCurrentBranch } from "./init-helpers.js";
35
+ function getMatchGroup(match, index = 1) {
36
+ const value = match?.[index];
37
+ return typeof value === "string" ? value : null;
38
+ }
34
39
  function buildManifestLookup(stagedFiles) {
35
40
  const manifestLookup = new Map();
36
41
  const manifestResults = [];
@@ -51,7 +56,8 @@ function buildManifestLookup(stagedFiles) {
51
56
  id: entry.entity.id,
52
57
  relationships: entry.relationships
53
58
  .filter((relationship) => relationship.type === "implements" ||
54
- relationship.type === "covered_by")
59
+ relationship.type === "covered_by" ||
60
+ relationship.type === "executable_for")
55
61
  .map((relationship) => ({
56
62
  type: relationship.type,
57
63
  to: relationship.to,
@@ -61,7 +67,7 @@ function buildManifestLookup(stagedFiles) {
61
67
  }
62
68
  catch (e) {
63
69
  // Ignore working-tree manifest parsing errors; staged-only fallback still applies
64
- if (process.env.KIBI_TRACE || process.env.KIBI_DEBUG) {
70
+ if (isCliTraceOrDebugEnabled()) {
65
71
  const msg = e instanceof Error ? e.message : String(e);
66
72
  console.debug(`[kibi] skipping working-tree manifest ${absSymbolsPath}: ${msg}`);
67
73
  }
@@ -91,7 +97,8 @@ function buildManifestLookup(stagedFiles) {
91
97
  id: entry.entity.id,
92
98
  relationships: entry.relationships
93
99
  .filter((relationship) => relationship.type === "implements" ||
94
- relationship.type === "covered_by")
100
+ relationship.type === "covered_by" ||
101
+ relationship.type === "executable_for")
95
102
  .map((relationship) => ({
96
103
  type: relationship.type,
97
104
  to: relationship.to,
@@ -115,7 +122,7 @@ export async function checkCommand(options) {
115
122
  resolvedKbPath = options.kbPath;
116
123
  }
117
124
  else {
118
- const envBranch = process.env.KIBI_BRANCH;
125
+ const envBranch = getBranchOverride();
119
126
  let branch = envBranch || undefined;
120
127
  if (!branch) {
121
128
  try {
@@ -329,8 +336,9 @@ async function checkMustPriorityCoverage(prolog) {
329
336
  if (entityResult.success && entityResult.bindings.Props) {
330
337
  const propsStr = entityResult.bindings.Props;
331
338
  const sourceMatch = propsStr.match(/source\s*=\s*\^\^?\("([^"]+)"/);
332
- if (sourceMatch) {
333
- source = sourceMatch[1];
339
+ const sourceValue = getMatchGroup(sourceMatch);
340
+ if (sourceValue) {
341
+ source = sourceValue;
334
342
  }
335
343
  }
336
344
  const scenarioResult = await prolog.query(`kb_relationship(specified_by, '${reqId}', ScenarioId)`);
@@ -366,10 +374,7 @@ async function findMustPriorityReqs(prolog) {
366
374
  }
367
375
  const idsStr = result.bindings.Ids;
368
376
  const match = idsStr.match(/\[(.*)\]/);
369
- if (!match) {
370
- return [];
371
- }
372
- const content = match[1].trim();
377
+ const content = getMatchGroup(match)?.trim();
373
378
  if (!content) {
374
379
  return [];
375
380
  }
@@ -384,10 +389,7 @@ async function getAllEntityIds(prolog, type) {
384
389
  }
385
390
  const idsStr = result.bindings.Ids;
386
391
  const match = idsStr.match(/\[(.*)\]/);
387
- if (!match) {
388
- return [];
389
- }
390
- const content = match[1].trim();
392
+ const content = getMatchGroup(match)?.trim();
391
393
  if (!content) {
392
394
  return [];
393
395
  }
@@ -412,15 +414,17 @@ async function checkNoDanglingRefs(prolog) {
412
414
  if (relsResult.success && relsResult.bindings.Rels) {
413
415
  const relsStr = relsResult.bindings.Rels;
414
416
  const match = relsStr.match(/\[(.*)\]/);
415
- if (match) {
416
- const content = match[1].trim();
417
- if (content) {
418
- const relMatches = content.matchAll(/\[([^,]+),([^\]]+)\]/g);
419
- for (const relMatch of relMatches) {
420
- const fromId = relMatch[1].trim().replace(/^'|'$/g, "");
421
- const toId = relMatch[2].trim().replace(/^'|'$/g, "");
422
- allRels.push({ from: fromId, to: toId });
423
- }
417
+ const content = getMatchGroup(match)?.trim();
418
+ if (content) {
419
+ const relMatches = content.matchAll(/\[([^,]+),([^\]]+)\]/g);
420
+ for (const relMatch of relMatches) {
421
+ const fromValue = getMatchGroup(relMatch);
422
+ const toValue = getMatchGroup(relMatch, 2);
423
+ if (!fromValue || !toValue)
424
+ continue;
425
+ const fromId = fromValue.trim().replace(/^'|'$/g, "");
426
+ const toId = toValue.trim().replace(/^'|'$/g, "");
427
+ allRels.push({ from: fromId, to: toId });
424
428
  }
425
429
  }
426
430
  }
@@ -454,18 +458,19 @@ async function checkNoCycles(prolog) {
454
458
  }
455
459
  const depsStr = depsResult.bindings.Deps;
456
460
  const match = depsStr.match(/\[(.*)\]/);
457
- if (!match) {
458
- return violations;
459
- }
460
- const content = match[1].trim();
461
+ const content = getMatchGroup(match)?.trim();
461
462
  if (!content) {
462
463
  return violations;
463
464
  }
464
465
  const graph = new Map();
465
466
  const depMatches = content.matchAll(/\[([^,]+),([^\]]+)\]/g);
466
467
  for (const depMatch of depMatches) {
467
- const from = depMatch[1].trim().replace(/^'|'$/g, "");
468
- const to = depMatch[2].trim().replace(/^'|'$/g, "");
468
+ const fromValue = getMatchGroup(depMatch);
469
+ const toValue = getMatchGroup(depMatch, 2);
470
+ if (!fromValue || !toValue)
471
+ continue;
472
+ const from = fromValue.trim().replace(/^'|'$/g, "");
473
+ const to = toValue.trim().replace(/^'|'$/g, "");
469
474
  if (!graph.has(from)) {
470
475
  graph.set(from, []);
471
476
  }
@@ -499,6 +504,10 @@ async function checkNoCycles(prolog) {
499
504
  if (!visited.has(node)) {
500
505
  const cyclePath = hasCycleDFS(node, []);
501
506
  if (cyclePath) {
507
+ const cycleEntityId = cyclePath[0];
508
+ if (!cycleEntityId) {
509
+ continue;
510
+ }
502
511
  const cycleWithSources = [];
503
512
  for (const entityId of cyclePath) {
504
513
  const entityResult = await prolog.query(`kb_entity('${entityId}', _, Props)`);
@@ -506,15 +515,16 @@ async function checkNoCycles(prolog) {
506
515
  if (entityResult.success && entityResult.bindings.Props) {
507
516
  const propsStr = entityResult.bindings.Props;
508
517
  const sourceMatch = propsStr.match(/source\s*=\s*\^\^?\("([^"]+)"/);
509
- if (sourceMatch) {
510
- sourceName = path.basename(sourceMatch[1], ".md");
518
+ const sourceValue = getMatchGroup(sourceMatch);
519
+ if (sourceValue) {
520
+ sourceName = path.basename(sourceValue, ".md");
511
521
  }
512
522
  }
513
523
  cycleWithSources.push(sourceName);
514
524
  }
515
525
  violations.push({
516
526
  rule: "no-cycles",
517
- entityId: cyclePath[0],
527
+ entityId: cycleEntityId,
518
528
  description: `Circular dependency detected: ${cycleWithSources.join(" → ")}`,
519
529
  suggestion: "Break cycle by removing one of the depends_on relationships",
520
530
  });
@@ -541,7 +551,10 @@ async function checkRequiredFields(prolog, allEntityIds) {
541
551
  const propKeys = new Set();
542
552
  const keyMatches = propsStr.matchAll(/(\w+)\s*=/g);
543
553
  for (const match of keyMatches) {
544
- propKeys.add(match[1]);
554
+ const key = getMatchGroup(match);
555
+ if (key) {
556
+ propKeys.add(key);
557
+ }
545
558
  }
546
559
  for (const field of required) {
547
560
  if (!propKeys.has(field)) {
@@ -566,10 +579,7 @@ async function checkDeprecatedAdrs(prolog) {
566
579
  }
567
580
  const idsStr = result.bindings.Ids;
568
581
  const match = idsStr.match(/\[(.*)\]/);
569
- if (!match) {
570
- return violations;
571
- }
572
- const content = match[1].trim();
582
+ const content = getMatchGroup(match)?.trim();
573
583
  if (!content) {
574
584
  return violations;
575
585
  }
@@ -582,8 +592,9 @@ async function checkDeprecatedAdrs(prolog) {
582
592
  if (entityResult.success && entityResult.bindings.Props) {
583
593
  const propsStr = entityResult.bindings.Props;
584
594
  const sourceMatch = propsStr.match(/source\s*=\s*\^\^?\("([^"]+)"/);
585
- if (sourceMatch) {
586
- source = sourceMatch[1];
595
+ const sourceValue = getMatchGroup(sourceMatch);
596
+ if (sourceValue) {
597
+ source = sourceValue;
587
598
  }
588
599
  }
589
600
  violations.push({
@@ -635,19 +646,19 @@ async function checkSymbolCoverage(prolog) {
635
646
  if (uncoveredResult.success && uncoveredResult.bindings.Symbols) {
636
647
  const symbolsStr = uncoveredResult.bindings.Symbols;
637
648
  const match = symbolsStr.match(/\[(.*)\]/);
638
- if (match) {
639
- const content = match[1].trim();
640
- if (content) {
641
- const symbolMatches = content.matchAll(/'([^']+)'/g);
642
- for (const symbolMatch of symbolMatches) {
643
- const symbolId = symbolMatch[1];
644
- violations.push({
645
- rule: "symbol-coverage",
646
- entityId: symbolId,
647
- description: "Code symbol is not traceable to any functional requirement.",
648
- suggestion: "Update symbols.yaml to link this symbol to a related requirement.",
649
- });
650
- }
649
+ const content = getMatchGroup(match)?.trim();
650
+ if (content) {
651
+ const symbolMatches = content.matchAll(/'([^']+)'/g);
652
+ for (const symbolMatch of symbolMatches) {
653
+ const symbolId = getMatchGroup(symbolMatch);
654
+ if (!symbolId)
655
+ continue;
656
+ violations.push({
657
+ rule: "symbol-coverage",
658
+ entityId: symbolId,
659
+ description: "Code symbol is not traceable to any functional requirement.",
660
+ suggestion: "Update symbols.yaml to link this symbol to a related requirement.",
661
+ });
651
662
  }
652
663
  }
653
664
  }
@@ -1,11 +1,18 @@
1
- import { PrologProcess } from "../prolog.js";
1
+ import { PrologProcess, resolveKbPlPath } from "../prolog.js";
2
2
  export interface DiscoveryCommandOptions {
3
3
  format?: "json" | "table";
4
4
  }
5
- export declare function withAttachedBranchProlog<T>(callback: (prolog: PrologProcess) => Promise<T>): Promise<T>;
6
- export declare function withPrologProcess<T>(callback: (prolog: PrologProcess) => Promise<T>): Promise<T>;
5
+ /** Dependencies that can be injected for testing. */
6
+ export interface DiscoveryDeps {
7
+ createProlog: (opts: {
8
+ timeout: number;
9
+ }) => PrologProcess;
10
+ resolveKbPl: typeof resolveKbPlPath;
11
+ }
12
+ export declare function withAttachedBranchProlog<T>(callback: (prolog: PrologProcess) => Promise<T>, deps?: Partial<DiscoveryDeps>): Promise<T>;
13
+ export declare function withPrologProcess<T>(callback: (prolog: PrologProcess) => Promise<T>, deps?: Partial<DiscoveryDeps>): Promise<T>;
7
14
  export declare function resolveCurrentKbPath(): Promise<string>;
8
- export declare function resolveCoreModulePath(fileName: string): string;
9
- export declare function runJsonModuleQuery<T>(prolog: PrologProcess, fileName: string, goal: string, errorLabel: string, kbPath?: string): Promise<T>;
15
+ export declare function resolveCoreModulePath(fileName: string, deps?: Partial<DiscoveryDeps>): string;
16
+ export declare function runJsonModuleQuery<T>(prolog: PrologProcess, fileName: string, goal: string, errorLabel: string, kbPath?: string, deps?: Partial<DiscoveryDeps>): Promise<T>;
10
17
  export declare function printDiscoveryResult(format: "json" | "table" | undefined, structured: unknown, fallbackText: string): void;
11
18
  //# sourceMappingURL=discovery-shared.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery-shared.d.ts","sourceRoot":"","sources":["../../src/commands/discovery-shared.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAmB,MAAM,cAAc,CAAC;AAK9D,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9C,OAAO,CAAC,CAAC,CAAC,CAkCZ;AAGD,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9C,OAAO,CAAC,CAAC,CAAC,CAYZ;AAGD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CAS5D;AAGD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AAGD,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,CAAC,CAAC,CAwBZ;AAGD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,EACpC,UAAU,EAAE,OAAO,EACnB,YAAY,EAAE,MAAM,GACnB,IAAI,CAQN"}
1
+ {"version":3,"file":"discovery-shared.d.ts","sourceRoot":"","sources":["../../src/commands/discovery-shared.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAK9D,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAED,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;IAC3D,WAAW,EAAE,OAAO,eAAe,CAAC;CACrC;AAGD,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,EAC/C,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,OAAO,CAAC,CAAC,CAAC,CAmCZ;AAGD,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,EAC/C,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,OAAO,CAAC,CAAC,CAAC,CAmBZ;AAGD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,CAS5D;AAGD,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,MAAM,CAGR;AAGD,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,OAAO,CAAC,CAAC,CAAC,CAwBZ;AAGD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,EACpC,UAAU,EAAE,OAAO,EACnB,YAAY,EAAE,MAAM,GACnB,IAAI,CAQN"}
@@ -1,24 +1,25 @@
1
1
  import path from "node:path";
2
2
  import Table from "cli-table3";
3
+ import { getBranchOverride } from "../env.js";
3
4
  import { PrologProcess, resolveKbPlPath } from "../prolog.js";
4
5
  import { escapeAtom } from "../prolog/codec.js";
5
6
  import { safeCleanupProlog } from "../utils/prolog-cleanup.js";
6
7
  import { getCurrentBranch } from "./init-helpers.js";
7
8
  // implements REQ-003
8
- export async function withAttachedBranchProlog(callback) {
9
+ export async function withAttachedBranchProlog(callback, deps) {
10
+ const createProlog = deps?.createProlog ?? ((opts) => new PrologProcess(opts));
9
11
  let prolog = null;
10
12
  let attached = false;
11
13
  try {
12
- prolog = new PrologProcess({ timeout: 120000 });
14
+ prolog = createProlog({ timeout: 120000 });
13
15
  await prolog.start();
14
16
  await prolog.query("set_prolog_flag(answer_write_options, [max_depth(0), spacing(next_argument)])");
15
17
  let branch;
16
18
  try {
17
- branch =
18
- process.env.KIBI_BRANCH || (await getCurrentBranch(process.cwd()));
19
+ branch = getBranchOverride() || (await getCurrentBranch(process.cwd()));
19
20
  }
20
21
  catch {
21
- branch = process.env.KIBI_BRANCH || "main";
22
+ branch = getBranchOverride() || "main";
22
23
  }
23
24
  const kbPath = path.join(process.cwd(), ".kb/branches", branch);
24
25
  const attachResult = await prolog.query(`kb_attach('${escapeAtom(kbPath)}')`);
@@ -33,10 +34,16 @@ export async function withAttachedBranchProlog(callback) {
33
34
  }
34
35
  }
35
36
  // implements REQ-003
36
- export async function withPrologProcess(callback) {
37
- const prolog = new PrologProcess({ timeout: 120000 });
37
+ export async function withPrologProcess(callback, deps) {
38
+ const createProlog = deps?.createProlog ?? ((opts) => new PrologProcess(opts));
39
+ const prolog = createProlog({ timeout: 120000 });
38
40
  try {
39
41
  await prolog.start();
42
+ // NOTE: useOneShotMode is an internal optimization flag on PrologProcess that
43
+ // forces single-query mode (start → query → terminate per call) instead of the
44
+ // default interactive session. It is not exposed in the public PrologProcess
45
+ // type because callers should not set it directly — only internal discovery
46
+ // helpers use it for lightweight one-shot queries that don't need session state.
40
47
  prolog.useOneShotMode = true;
41
48
  await prolog.query("set_prolog_flag(answer_write_options, [max_depth(0), spacing(next_argument)])");
42
49
  return await callback(prolog);
@@ -49,20 +56,21 @@ export async function withPrologProcess(callback) {
49
56
  export async function resolveCurrentKbPath() {
50
57
  let branch;
51
58
  try {
52
- branch = process.env.KIBI_BRANCH || (await getCurrentBranch(process.cwd()));
59
+ branch = getBranchOverride() || (await getCurrentBranch(process.cwd()));
53
60
  }
54
61
  catch {
55
- branch = process.env.KIBI_BRANCH || "main";
62
+ branch = getBranchOverride() || "main";
56
63
  }
57
64
  return path.join(process.cwd(), ".kb/branches", branch);
58
65
  }
59
66
  // implements REQ-003
60
- export function resolveCoreModulePath(fileName) {
61
- return path.join(path.dirname(resolveKbPlPath()), fileName);
67
+ export function resolveCoreModulePath(fileName, deps) {
68
+ const resolve = deps?.resolveKbPl ?? resolveKbPlPath;
69
+ return path.join(path.dirname(resolve()), fileName);
62
70
  }
63
71
  // implements REQ-003
64
- export async function runJsonModuleQuery(prolog, fileName, goal, errorLabel, kbPath) {
65
- const modulePath = escapeAtom(resolveCoreModulePath(fileName).replace(/\\/g, "/"));
72
+ export async function runJsonModuleQuery(prolog, fileName, goal, errorLabel, kbPath, deps) {
73
+ const modulePath = escapeAtom(resolveCoreModulePath(fileName, deps).replace(/\\/g, "/"));
66
74
  const wrappedGoal = kbPath
67
75
  ? `(use_module('${modulePath}'), kb_attach('${escapeAtom(kbPath)}'), ${goal}, kb_detach)`
68
76
  : `(use_module('${modulePath}'), ${goal})`;
@@ -82,7 +82,15 @@ function checkSWIProlog() {
82
82
  remediation: "Reinstall SWI-Prolog from https://www.swi-prolog.org/",
83
83
  };
84
84
  }
85
- const major = Number.parseInt(versionMatch[1], 10);
85
+ const majorText = versionMatch[1];
86
+ if (!majorText) {
87
+ return {
88
+ passed: false,
89
+ message: "Unable to parse major version",
90
+ remediation: "Reinstall SWI-Prolog from https://www.swi-prolog.org/",
91
+ };
92
+ }
93
+ const major = Number.parseInt(majorText, 10);
86
94
  if (major < 9) {
87
95
  return {
88
96
  passed: false,
@@ -1 +1 @@
1
- {"version":3,"file":"init-helpers.d.ts","sourceRoot":"","sources":["../../src/commands/init-helpers.ts"],"names":[],"mappings":"AAuFA,wBAAsB,gBAAgB,CACpC,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,IAAI,CAQN;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAMpD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAajD;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAYf;AASD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAmCnE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAiBpD"}
1
+ {"version":3,"file":"init-helpers.d.ts","sourceRoot":"","sources":["../../src/commands/init-helpers.ts"],"names":[],"mappings":"AAuFA,wBAAsB,gBAAgB,CACpC,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,IAAI,CAQN;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAMpD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAajD;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAYf;AASD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAkCnE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAiBpD"}
@@ -121,6 +121,7 @@ function escapeRegex(s) {
121
121
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
122
122
  }
123
123
  export function installHook(hookPath, content) {
124
+ // implements REQ-008
124
125
  const kibiSection = `${KIBI_HOOK_BEGIN}\n${content}\n${KIBI_HOOK_END}`;
125
126
  if (existsSync(hookPath)) {
126
127
  const existing = readFileSync(hookPath, "utf8");
@@ -130,12 +131,10 @@ export function installHook(hookPath, content) {
130
131
  const updated = existing.replace(new RegExp(`${escapeRegex(KIBI_HOOK_BEGIN)}[\\s\\S]*?${escapeRegex(KIBI_HOOK_END)}`), kibiSection);
131
132
  writeFileSync(hookPath, updated, { mode: 0o755 });
132
133
  }
133
- else if (existing.includes("kibi branch ensure")) {
134
- // Legacy format: already has the complete kibi logic, skip
134
+ else if (existing.trim().length > 0) {
135
135
  return;
136
136
  }
137
137
  else {
138
- // Hook exists with user content (no kibi section) - append kibi section
139
138
  const shebang = existing.startsWith("#!/") ? "" : "#!/bin/sh\n";
140
139
  writeFileSync(hookPath, `${shebang}${existing.trimEnd()}\n${kibiSection}\n`, { mode: 0o755 });
141
140
  }
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AA4CA,UAAU,YAAY;IACpB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAGD,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA+J/B"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AA4CA,UAAU,YAAY;IACpB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAGD,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA4K/B"}
@@ -71,11 +71,21 @@ export async function queryCommand(type, options) {
71
71
  const rows = parseListOfLists(queryResult.bindings.Results);
72
72
  const parsed = rows
73
73
  .filter((r) => r.length >= 3)
74
- .map((r) => ({
75
- type: parsePrologValue(r[0]),
76
- from: parsePrologValue(r[1]),
77
- to: parsePrologValue(r[2]),
78
- }));
74
+ .flatMap((r) => {
75
+ const [typeValue, fromValue, toValue] = r;
76
+ if (typeValue === undefined ||
77
+ fromValue === undefined ||
78
+ toValue === undefined) {
79
+ return [];
80
+ }
81
+ return [
82
+ {
83
+ type: parsePrologValue(typeValue),
84
+ from: parsePrologValue(fromValue),
85
+ to: parsePrologValue(toValue),
86
+ },
87
+ ];
88
+ });
79
89
  results = parsed.filter((rel) => rel &&
80
90
  typeof rel.type === "string" &&
81
91
  typeof rel.from === "string" &&
@@ -22,7 +22,7 @@ export async function searchCommand(query, options) {
22
22
  }
23
23
  async function executeSearch(prolog, query, type, limit, offset) {
24
24
  const entitiesResult = await queryEntities(prolog, {
25
- type,
25
+ ...(type !== undefined ? { type } : {}),
26
26
  limit: 100000,
27
27
  offset: 0,
28
28
  });
@@ -1,3 +1,12 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ interface SyncCacheDeps {
4
+ createHash: typeof createHash;
5
+ existsSync: typeof existsSync;
6
+ mkdirSync: typeof mkdirSync;
7
+ readFileSync: typeof readFileSync;
8
+ writeFileSync: typeof writeFileSync;
9
+ }
1
10
  export type SyncCache = {
2
11
  version: number;
3
12
  hashes: Record<string, string>;
@@ -6,8 +15,9 @@ export type SyncCache = {
6
15
  export declare const SYNC_CACHE_VERSION = 1;
7
16
  export declare const SYNC_CACHE_TTL_MS: number;
8
17
  export declare function toCacheKey(filePath: string): string;
9
- export declare function hashFile(filePath: string): string;
10
- export declare function readSyncCache(cachePath: string): SyncCache;
11
- export declare function writeSyncCache(cachePath: string, cache: SyncCache): void;
12
- export declare function copySyncCache(livePath: string, stagingPath: string): void;
18
+ export declare function hashFile(filePath: string, deps?: Partial<SyncCacheDeps>): string;
19
+ export declare function readSyncCache(cachePath: string, deps?: Partial<SyncCacheDeps>): SyncCache;
20
+ export declare function writeSyncCache(cachePath: string, cache: SyncCache, deps?: Partial<SyncCacheDeps>): void;
21
+ export declare function copySyncCache(livePath: string, stagingPath: string, deps?: Partial<SyncCacheDeps>): void;
22
+ export {};
13
23
  //# sourceMappingURL=cache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/cache.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,iBAAiB,QAA2B,CAAC;AAE1D,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAiC1D;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAYxE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAQzE"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/cache.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7E,UAAU,aAAa;IACrB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,aAAa,EAAE,OAAO,aAAa,CAAC;CACrC;AAaD,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,iBAAiB,QAA2B,CAAC;AAE1D,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,QAAQ,CAEtB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,MAAM,CAIR;AAED,wBAAgB,aAAa,CAE3B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,SAAS,CAkCX;AAED,wBAAgB,cAAc,CAE5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,IAAI,CAaN;AAED,wBAAgB,aAAa,CAE3B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,IAAI,CASN"}
@@ -18,17 +18,33 @@
18
18
  import { createHash } from "node:crypto";
19
19
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
20
20
  import * as path from "node:path";
21
+ function resolveDeps(overrides) {
22
+ return {
23
+ createHash,
24
+ existsSync,
25
+ mkdirSync,
26
+ readFileSync,
27
+ writeFileSync,
28
+ ...overrides,
29
+ };
30
+ }
21
31
  export const SYNC_CACHE_VERSION = 1;
22
32
  export const SYNC_CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
23
33
  export function toCacheKey(filePath) {
24
34
  return path.relative(process.cwd(), filePath).split(path.sep).join("/");
25
35
  }
26
- export function hashFile(filePath) {
27
- const content = readFileSync(filePath);
28
- return createHash("sha256").update(content).digest("hex");
36
+ export function hashFile(
37
+ // implements REQ-003
38
+ filePath, deps) {
39
+ const resolved = resolveDeps(deps);
40
+ const content = resolved.readFileSync(filePath);
41
+ return resolved.createHash("sha256").update(content).digest("hex");
29
42
  }
30
- export function readSyncCache(cachePath) {
31
- if (!existsSync(cachePath)) {
43
+ export function readSyncCache(
44
+ // implements REQ-003
45
+ cachePath, deps) {
46
+ const resolved = resolveDeps(deps);
47
+ if (!resolved.existsSync(cachePath)) {
32
48
  return {
33
49
  version: SYNC_CACHE_VERSION,
34
50
  hashes: {},
@@ -36,7 +52,7 @@ export function readSyncCache(cachePath) {
36
52
  };
37
53
  }
38
54
  try {
39
- const parsed = JSON.parse(readFileSync(cachePath, "utf8"));
55
+ const parsed = JSON.parse(resolved.readFileSync(cachePath, "utf8"));
40
56
  if (parsed.version !== SYNC_CACHE_VERSION) {
41
57
  return {
42
58
  version: SYNC_CACHE_VERSION,
@@ -58,19 +74,25 @@ export function readSyncCache(cachePath) {
58
74
  };
59
75
  }
60
76
  }
61
- export function writeSyncCache(cachePath, cache) {
77
+ export function writeSyncCache(
78
+ // implements REQ-003
79
+ cachePath, cache, deps) {
80
+ const resolved = resolveDeps(deps);
62
81
  const cacheDir = path.dirname(cachePath);
63
- if (!existsSync(cacheDir)) {
64
- mkdirSync(cacheDir, { recursive: true });
82
+ if (!resolved.existsSync(cacheDir)) {
83
+ resolved.mkdirSync(cacheDir, { recursive: true });
65
84
  }
66
- writeFileSync(cachePath, `${JSON.stringify(cache, null, 2)}
85
+ resolved.writeFileSync(cachePath, `${JSON.stringify(cache, null, 2)}
67
86
  `, "utf8");
68
87
  }
69
- export function copySyncCache(livePath, stagingPath) {
88
+ export function copySyncCache(
89
+ // implements REQ-003
90
+ livePath, stagingPath, deps) {
91
+ const resolved = resolveDeps(deps);
70
92
  const liveCachePath = path.join(livePath, "sync-cache.json");
71
93
  const stagingCachePath = path.join(stagingPath, "sync-cache.json");
72
- if (existsSync(liveCachePath)) {
73
- const cacheContent = readFileSync(liveCachePath, "utf8");
74
- writeFileSync(stagingCachePath, cacheContent, "utf8");
94
+ if (resolved.existsSync(liveCachePath)) {
95
+ const cacheContent = resolved.readFileSync(liveCachePath, "utf8");
96
+ resolved.writeFileSync(stagingCachePath, cacheContent, "utf8");
75
97
  }
76
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/extraction.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7C;AAED,wBAAsB,kBAAkB,CACtC,oBAAoB,EAAE,MAAM,EAAE,EAC9B,oBAAoB,EAAE,MAAM,EAAE,EAC9B,YAAY,EAAE,OAAO,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAoD3B"}
1
+ {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/extraction.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7C;AAED,wBAAsB,kBAAkB,CAEtC,oBAAoB,EAAE,MAAM,EAAE,EAC9B,oBAAoB,EAAE,MAAM,EAAE,EAC9B,YAAY,EAAE,OAAO,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA4C3B"}
@@ -18,7 +18,9 @@
18
18
  import { extractFromManifest } from "../../extractors/manifest.js";
19
19
  import { FrontmatterError, extractFromMarkdown, } from "../../extractors/markdown.js";
20
20
  import { toCacheKey } from "./cache.js";
21
- export async function processExtractions(changedMarkdownFiles, changedManifestFiles, validateOnly) {
21
+ export async function processExtractions(
22
+ // implements REQ-003
23
+ changedMarkdownFiles, changedManifestFiles, validateOnly) {
22
24
  const results = [];
23
25
  const failedCacheKeys = new Set();
24
26
  const errors = [];
@@ -31,14 +33,7 @@ export async function processExtractions(changedMarkdownFiles, changedManifestFi
31
33
  // Handle INVALID_AUTHORING diagnostics for embedded entities
32
34
  if (error instanceof FrontmatterError &&
33
35
  error.classification === "Embedded Entity Violation") {
34
- const embeddedTypes = message.includes("scenario") && message.includes("test")
35
- ? ["scenario", "test"]
36
- : message.includes("scenario")
37
- ? ["scenario"]
38
- : message.includes("test")
39
- ? ["test"]
40
- : ["entity"];
41
- // Note: diagnostics are created by the caller
36
+ // Note: diagnostics with embeddedTypes are created by the caller (sync.ts)
42
37
  }
43
38
  if (validateOnly) {
44
39
  errors.push({ file, message });