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.
- package/dist/commands/aggregated-checks.d.ts.map +1 -1
- package/dist/commands/aggregated-checks.js +3 -2
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +97 -51
- package/dist/commands/discovery-shared.d.ts +12 -5
- package/dist/commands/discovery-shared.d.ts.map +1 -1
- package/dist/commands/discovery-shared.js +21 -13
- package/dist/commands/doctor.js +9 -1
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +2 -3
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +15 -5
- package/dist/commands/search.js +1 -1
- package/dist/commands/sync/cache.d.ts +14 -4
- package/dist/commands/sync/cache.d.ts.map +1 -1
- package/dist/commands/sync/cache.js +36 -14
- package/dist/commands/sync/extraction.d.ts.map +1 -1
- package/dist/commands/sync/extraction.js +4 -9
- package/dist/commands/sync/manifest.d.ts +14 -3
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +29 -10
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +9 -5
- package/dist/commands/sync/staging.d.ts +19 -3
- package/dist/commands/sync/staging.d.ts.map +1 -1
- package/dist/commands/sync/staging.js +50 -27
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +16 -20
- package/dist/diagnostics.d.ts +1 -10
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +6 -12
- package/dist/env.d.ts +7 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +41 -0
- package/dist/extractors/manifest.d.ts.map +1 -1
- package/dist/extractors/manifest.js +17 -15
- package/dist/extractors/markdown.d.ts +2 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +124 -30
- package/dist/extractors/relationships.d.ts.map +1 -1
- package/dist/extractors/relationships.js +10 -4
- package/dist/extractors/symbols-coordinator.d.ts +5 -2
- package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
- package/dist/extractors/symbols-coordinator.js +5 -2
- package/dist/extractors/symbols-ts.d.ts.map +1 -1
- package/dist/extractors/symbols-ts.js +56 -10
- package/dist/prolog/codec.d.ts +0 -43
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +68 -74
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +45 -29
- package/dist/public/schemas/entity.d.ts +3 -0
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +1 -0
- package/dist/public/schemas/relationship.d.ts.map +1 -1
- package/dist/public/schemas/relationship.js +1 -0
- package/dist/query/service.d.ts +9 -0
- package/dist/query/service.d.ts.map +1 -1
- package/dist/query/service.js +27 -10
- package/dist/schemas/entity.schema.json +23 -0
- package/dist/search-ranking.d.ts.map +1 -1
- package/dist/search-ranking.js +19 -3
- package/dist/traceability/git-staged.d.ts.map +1 -1
- package/dist/traceability/git-staged.js +22 -6
- package/dist/traceability/symbol-extract.d.ts.map +1 -1
- package/dist/traceability/symbol-extract.js +10 -4
- package/dist/traceability/temp-kb.d.ts +12 -0
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +42 -17
- package/dist/traceability/validate.d.ts.map +1 -1
- package/dist/traceability/validate.js +11 -2
- package/dist/utils/branch-resolver.d.ts +4 -0
- package/dist/utils/branch-resolver.d.ts.map +1 -1
- package/dist/utils/branch-resolver.js +29 -12
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +8 -2
- package/dist/utils/rule-registry.js +2 -2
- package/package.json +3 -9
- package/src/public/schemas/entity.ts +1 -0
- package/src/public/schemas/relationship.ts +1 -0
- package/src/schemas/entity.schema.json +23 -0
- 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,
|
|
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
|
|
52
|
-
source: v.source
|
|
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":"
|
|
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"}
|
package/dist/commands/check.js
CHANGED
|
@@ -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 {
|
|
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 =
|
|
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
|
-
|
|
298
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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
|
-
|
|
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
|
|
433
|
-
const
|
|
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
|
-
|
|
475
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
551
|
-
|
|
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
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
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
|
-
|
|
6
|
-
export
|
|
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":"
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
59
|
+
branch = getBranchOverride() || (await getCurrentBranch(process.cwd()));
|
|
53
60
|
}
|
|
54
61
|
catch {
|
|
55
|
-
branch =
|
|
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
|
-
|
|
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})`;
|
package/dist/commands/doctor.js
CHANGED
|
@@ -82,7 +82,15 @@ function checkSWIProlog() {
|
|
|
82
82
|
remediation: "Reinstall SWI-Prolog from https://www.swi-prolog.org/",
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
|
-
const
|
|
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,
|
|
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.
|
|
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,
|
|
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"}
|
package/dist/commands/query.js
CHANGED
|
@@ -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
|
-
.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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" &&
|
package/dist/commands/search.js
CHANGED
|
@@ -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":"
|
|
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(
|
|
27
|
-
|
|
28
|
-
|
|
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(
|
|
31
|
-
|
|
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(
|
|
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(
|
|
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,
|
|
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"}
|