kibi-cli 0.5.0 → 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 (82) 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 +97 -51
  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 +45 -29
  52. package/dist/public/schemas/entity.d.ts +3 -0
  53. package/dist/public/schemas/entity.d.ts.map +1 -1
  54. package/dist/public/schemas/entity.js +1 -0
  55. package/dist/public/schemas/relationship.d.ts.map +1 -1
  56. package/dist/public/schemas/relationship.js +1 -0
  57. package/dist/query/service.d.ts +9 -0
  58. package/dist/query/service.d.ts.map +1 -1
  59. package/dist/query/service.js +27 -10
  60. package/dist/schemas/entity.schema.json +23 -0
  61. package/dist/search-ranking.d.ts.map +1 -1
  62. package/dist/search-ranking.js +19 -3
  63. package/dist/traceability/git-staged.d.ts.map +1 -1
  64. package/dist/traceability/git-staged.js +22 -6
  65. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  66. package/dist/traceability/symbol-extract.js +10 -4
  67. package/dist/traceability/temp-kb.d.ts +12 -0
  68. package/dist/traceability/temp-kb.d.ts.map +1 -1
  69. package/dist/traceability/temp-kb.js +42 -17
  70. package/dist/traceability/validate.d.ts.map +1 -1
  71. package/dist/traceability/validate.js +11 -2
  72. package/dist/utils/branch-resolver.d.ts +4 -0
  73. package/dist/utils/branch-resolver.d.ts.map +1 -1
  74. package/dist/utils/branch-resolver.js +29 -12
  75. package/dist/utils/config.d.ts.map +1 -1
  76. package/dist/utils/config.js +8 -2
  77. package/dist/utils/rule-registry.js +2 -2
  78. package/package.json +3 -9
  79. package/src/public/schemas/entity.ts +1 -0
  80. package/src/public/schemas/relationship.ts +1 -0
  81. package/src/schemas/entity.schema.json +23 -0
  82. 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":"AAkDA,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;AA4DD,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"}
@@ -15,8 +15,10 @@
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
+ import { existsSync } from "node:fs";
18
19
  import * as path from "node:path";
19
- import { extractFromManifestString } from "../extractors/manifest.js";
20
+ import { getBranchOverride, isCliTraceOrDebugEnabled } from "../env.js";
21
+ import { extractFromManifest, extractFromManifestString, } from "../extractors/manifest.js";
20
22
  import { extractFromMarkdownString, } from "../extractors/markdown.js";
21
23
  import { PrologProcess } from "../prolog.js";
22
24
  import { escapeAtom, parseTriples, parseViolationRows, } from "../prolog/codec.js";
@@ -30,9 +32,48 @@ import { safeCleanupProlog } from "../utils/prolog-cleanup.js";
30
32
  import { RULES, getEffectiveRules, } from "../utils/rule-registry.js";
31
33
  import { runAggregatedChecks } from "./aggregated-checks.js";
32
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
+ }
33
39
  function buildManifestLookup(stagedFiles) {
34
40
  const manifestLookup = new Map();
35
41
  const manifestResults = [];
42
+ // Pre-populate lookup from working-tree manifests so that code-only changes
43
+ // (where symbols.yaml is not staged) still resolve to the correct symbol IDs
44
+ // and relationships already defined on disk.
45
+ const config = loadConfig(process.cwd());
46
+ const symbolsRelPath = config.paths.symbols;
47
+ if (symbolsRelPath) {
48
+ const absSymbolsPath = path.resolve(process.cwd(), symbolsRelPath);
49
+ if (existsSync(absSymbolsPath)) {
50
+ try {
51
+ const entries = extractFromManifest(absSymbolsPath);
52
+ for (const entry of entries) {
53
+ const sourceFile = entry.sourceFile || entry.entity.source || absSymbolsPath;
54
+ const key = `${sourceFile}:${entry.entity.title}`;
55
+ manifestLookup.set(key, {
56
+ id: entry.entity.id,
57
+ relationships: entry.relationships
58
+ .filter((relationship) => relationship.type === "implements" ||
59
+ relationship.type === "covered_by" ||
60
+ relationship.type === "executable_for")
61
+ .map((relationship) => ({
62
+ type: relationship.type,
63
+ to: relationship.to,
64
+ })),
65
+ });
66
+ }
67
+ }
68
+ catch (e) {
69
+ // Ignore working-tree manifest parsing errors; staged-only fallback still applies
70
+ if (isCliTraceOrDebugEnabled()) {
71
+ const msg = e instanceof Error ? e.message : String(e);
72
+ console.debug(`[kibi] skipping working-tree manifest ${absSymbolsPath}: ${msg}`);
73
+ }
74
+ }
75
+ }
76
+ }
36
77
  const stagedManifestFiles = stagedFiles.filter((file) => file.content !== undefined &&
37
78
  (file.path.endsWith("/symbols.yaml") ||
38
79
  file.path.endsWith("/symbols.yml") ||
@@ -56,7 +97,8 @@ function buildManifestLookup(stagedFiles) {
56
97
  id: entry.entity.id,
57
98
  relationships: entry.relationships
58
99
  .filter((relationship) => relationship.type === "implements" ||
59
- relationship.type === "covered_by")
100
+ relationship.type === "covered_by" ||
101
+ relationship.type === "executable_for")
60
102
  .map((relationship) => ({
61
103
  type: relationship.type,
62
104
  to: relationship.to,
@@ -80,7 +122,7 @@ export async function checkCommand(options) {
80
122
  resolvedKbPath = options.kbPath;
81
123
  }
82
124
  else {
83
- const envBranch = process.env.KIBI_BRANCH;
125
+ const envBranch = getBranchOverride();
84
126
  let branch = envBranch || undefined;
85
127
  if (!branch) {
86
128
  try {
@@ -294,8 +336,9 @@ async function checkMustPriorityCoverage(prolog) {
294
336
  if (entityResult.success && entityResult.bindings.Props) {
295
337
  const propsStr = entityResult.bindings.Props;
296
338
  const sourceMatch = propsStr.match(/source\s*=\s*\^\^?\("([^"]+)"/);
297
- if (sourceMatch) {
298
- source = sourceMatch[1];
339
+ const sourceValue = getMatchGroup(sourceMatch);
340
+ if (sourceValue) {
341
+ source = sourceValue;
299
342
  }
300
343
  }
301
344
  const scenarioResult = await prolog.query(`kb_relationship(specified_by, '${reqId}', ScenarioId)`);
@@ -331,10 +374,7 @@ async function findMustPriorityReqs(prolog) {
331
374
  }
332
375
  const idsStr = result.bindings.Ids;
333
376
  const match = idsStr.match(/\[(.*)\]/);
334
- if (!match) {
335
- return [];
336
- }
337
- const content = match[1].trim();
377
+ const content = getMatchGroup(match)?.trim();
338
378
  if (!content) {
339
379
  return [];
340
380
  }
@@ -349,10 +389,7 @@ async function getAllEntityIds(prolog, type) {
349
389
  }
350
390
  const idsStr = result.bindings.Ids;
351
391
  const match = idsStr.match(/\[(.*)\]/);
352
- if (!match) {
353
- return [];
354
- }
355
- const content = match[1].trim();
392
+ const content = getMatchGroup(match)?.trim();
356
393
  if (!content) {
357
394
  return [];
358
395
  }
@@ -377,15 +414,17 @@ async function checkNoDanglingRefs(prolog) {
377
414
  if (relsResult.success && relsResult.bindings.Rels) {
378
415
  const relsStr = relsResult.bindings.Rels;
379
416
  const match = relsStr.match(/\[(.*)\]/);
380
- if (match) {
381
- const content = match[1].trim();
382
- if (content) {
383
- const relMatches = content.matchAll(/\[([^,]+),([^\]]+)\]/g);
384
- for (const relMatch of relMatches) {
385
- const fromId = relMatch[1].trim().replace(/^'|'$/g, "");
386
- const toId = relMatch[2].trim().replace(/^'|'$/g, "");
387
- allRels.push({ from: fromId, to: toId });
388
- }
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 });
389
428
  }
390
429
  }
391
430
  }
@@ -419,18 +458,19 @@ async function checkNoCycles(prolog) {
419
458
  }
420
459
  const depsStr = depsResult.bindings.Deps;
421
460
  const match = depsStr.match(/\[(.*)\]/);
422
- if (!match) {
423
- return violations;
424
- }
425
- const content = match[1].trim();
461
+ const content = getMatchGroup(match)?.trim();
426
462
  if (!content) {
427
463
  return violations;
428
464
  }
429
465
  const graph = new Map();
430
466
  const depMatches = content.matchAll(/\[([^,]+),([^\]]+)\]/g);
431
467
  for (const depMatch of depMatches) {
432
- const from = depMatch[1].trim().replace(/^'|'$/g, "");
433
- 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, "");
434
474
  if (!graph.has(from)) {
435
475
  graph.set(from, []);
436
476
  }
@@ -464,6 +504,10 @@ async function checkNoCycles(prolog) {
464
504
  if (!visited.has(node)) {
465
505
  const cyclePath = hasCycleDFS(node, []);
466
506
  if (cyclePath) {
507
+ const cycleEntityId = cyclePath[0];
508
+ if (!cycleEntityId) {
509
+ continue;
510
+ }
467
511
  const cycleWithSources = [];
468
512
  for (const entityId of cyclePath) {
469
513
  const entityResult = await prolog.query(`kb_entity('${entityId}', _, Props)`);
@@ -471,15 +515,16 @@ async function checkNoCycles(prolog) {
471
515
  if (entityResult.success && entityResult.bindings.Props) {
472
516
  const propsStr = entityResult.bindings.Props;
473
517
  const sourceMatch = propsStr.match(/source\s*=\s*\^\^?\("([^"]+)"/);
474
- if (sourceMatch) {
475
- sourceName = path.basename(sourceMatch[1], ".md");
518
+ const sourceValue = getMatchGroup(sourceMatch);
519
+ if (sourceValue) {
520
+ sourceName = path.basename(sourceValue, ".md");
476
521
  }
477
522
  }
478
523
  cycleWithSources.push(sourceName);
479
524
  }
480
525
  violations.push({
481
526
  rule: "no-cycles",
482
- entityId: cyclePath[0],
527
+ entityId: cycleEntityId,
483
528
  description: `Circular dependency detected: ${cycleWithSources.join(" → ")}`,
484
529
  suggestion: "Break cycle by removing one of the depends_on relationships",
485
530
  });
@@ -506,7 +551,10 @@ async function checkRequiredFields(prolog, allEntityIds) {
506
551
  const propKeys = new Set();
507
552
  const keyMatches = propsStr.matchAll(/(\w+)\s*=/g);
508
553
  for (const match of keyMatches) {
509
- propKeys.add(match[1]);
554
+ const key = getMatchGroup(match);
555
+ if (key) {
556
+ propKeys.add(key);
557
+ }
510
558
  }
511
559
  for (const field of required) {
512
560
  if (!propKeys.has(field)) {
@@ -531,10 +579,7 @@ async function checkDeprecatedAdrs(prolog) {
531
579
  }
532
580
  const idsStr = result.bindings.Ids;
533
581
  const match = idsStr.match(/\[(.*)\]/);
534
- if (!match) {
535
- return violations;
536
- }
537
- const content = match[1].trim();
582
+ const content = getMatchGroup(match)?.trim();
538
583
  if (!content) {
539
584
  return violations;
540
585
  }
@@ -547,8 +592,9 @@ async function checkDeprecatedAdrs(prolog) {
547
592
  if (entityResult.success && entityResult.bindings.Props) {
548
593
  const propsStr = entityResult.bindings.Props;
549
594
  const sourceMatch = propsStr.match(/source\s*=\s*\^\^?\("([^"]+)"/);
550
- if (sourceMatch) {
551
- source = sourceMatch[1];
595
+ const sourceValue = getMatchGroup(sourceMatch);
596
+ if (sourceValue) {
597
+ source = sourceValue;
552
598
  }
553
599
  }
554
600
  violations.push({
@@ -600,19 +646,19 @@ async function checkSymbolCoverage(prolog) {
600
646
  if (uncoveredResult.success && uncoveredResult.bindings.Symbols) {
601
647
  const symbolsStr = uncoveredResult.bindings.Symbols;
602
648
  const match = symbolsStr.match(/\[(.*)\]/);
603
- if (match) {
604
- const content = match[1].trim();
605
- if (content) {
606
- const symbolMatches = content.matchAll(/'([^']+)'/g);
607
- for (const symbolMatch of symbolMatches) {
608
- const symbolId = symbolMatch[1];
609
- violations.push({
610
- rule: "symbol-coverage",
611
- entityId: symbolId,
612
- description: "Code symbol is not traceable to any functional requirement.",
613
- suggestion: "Update symbols.yaml to link this symbol to a related requirement.",
614
- });
615
- }
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
+ });
616
662
  }
617
663
  }
618
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"}