kibi-cli 0.3.0 → 0.4.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/cli.d.ts +4 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +31 -16
- package/dist/commands/check.d.ts +5 -8
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +41 -62
- package/dist/commands/discovery-shared.d.ts.map +1 -1
- package/dist/commands/discovery-shared.js +23 -22
- package/dist/commands/doctor.d.ts +3 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +4 -5
- package/dist/commands/init.d.ts +3 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +4 -3
- package/dist/commands/query.d.ts +3 -1
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +9 -20
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +1 -1
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +79 -12
- package/dist/commands/sync.d.ts +4 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +79 -31
- package/dist/extractors/markdown.d.ts +17 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +104 -14
- package/dist/prolog/codec.d.ts +32 -5
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +95 -58
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +12 -2
- package/dist/public/check-types.d.ts +7 -0
- package/dist/public/check-types.d.ts.map +1 -0
- package/dist/public/check-types.js +18 -0
- package/dist/public/schemas/entity.d.ts +68 -0
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +52 -0
- package/dist/relationships/shards.d.ts.map +1 -1
- package/dist/relationships/shards.js +6 -3
- package/dist/schemas/entity.schema.json +120 -0
- package/dist/search-ranking.d.ts.map +1 -1
- package/dist/search-ranking.js +9 -3
- package/dist/traceability/symbol-extract.d.ts.map +1 -1
- package/dist/traceability/symbol-extract.js +16 -8
- package/dist/types/entities.d.ts +19 -1
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/utils/prolog-cleanup.d.ts +10 -0
- package/dist/utils/prolog-cleanup.d.ts.map +1 -0
- package/dist/utils/prolog-cleanup.js +39 -0
- package/dist/utils/rule-registry.d.ts +8 -0
- package/dist/utils/rule-registry.d.ts.map +1 -1
- package/dist/utils/rule-registry.js +14 -12
- package/package.json +6 -2
- package/schema/config.json +7 -1
- package/schema/entities.pl +18 -0
- package/schema/validation.pl +115 -4
- package/src/public/check-types.ts +37 -0
- package/src/public/schemas/entity.ts +58 -0
- package/src/schemas/entity.schema.json +56 -1
- package/dist/kb/target-resolver.d.ts +0 -80
- package/dist/kb/target-resolver.d.ts.map +0 -1
- package/dist/kb/target-resolver.js +0 -313
package/dist/cli.d.ts
CHANGED
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAsCA,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
package/dist/cli.js
CHANGED
|
@@ -31,6 +31,16 @@ import { statusCommand } from "./commands/status.js";
|
|
|
31
31
|
import { syncCommand } from "./commands/sync.js";
|
|
32
32
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
33
33
|
const VERSION = packageJson.version ?? "0.1.0";
|
|
34
|
+
// implements REQ-003
|
|
35
|
+
/** Wraps an async command handler to apply its returned exitCode to process.exitCode. */
|
|
36
|
+
function withExitCode(fn) {
|
|
37
|
+
return async (...args) => {
|
|
38
|
+
const result = await fn(...args);
|
|
39
|
+
if (result && typeof result.exitCode === "number") {
|
|
40
|
+
process.exitCode = result.exitCode;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
34
44
|
const program = new Command();
|
|
35
45
|
program
|
|
36
46
|
.name("kibi")
|
|
@@ -40,17 +50,17 @@ program
|
|
|
40
50
|
.command("init")
|
|
41
51
|
.description("Initialize .kb/ directory")
|
|
42
52
|
.option("--no-hooks", "Do not install git hooks (hooks installed by default)")
|
|
43
|
-
.action(async (options) => {
|
|
44
|
-
|
|
45
|
-
});
|
|
53
|
+
.action(withExitCode(async (options) => {
|
|
54
|
+
return initCommand(options);
|
|
55
|
+
}));
|
|
46
56
|
program
|
|
47
57
|
.command("sync")
|
|
48
58
|
.description("Sync entities from documents")
|
|
49
59
|
.option("--validate-only", "Perform validation without mutations")
|
|
50
60
|
.option("--rebuild", "Rebuild branch snapshot from scratch (discards current KB)")
|
|
51
|
-
.action(async (options) => {
|
|
52
|
-
|
|
53
|
-
});
|
|
61
|
+
.action(withExitCode(async (options) => {
|
|
62
|
+
return syncCommand(options);
|
|
63
|
+
}));
|
|
54
64
|
program
|
|
55
65
|
.command("query [type]")
|
|
56
66
|
.description("Query knowledge base")
|
|
@@ -61,9 +71,9 @@ program
|
|
|
61
71
|
.option("--format <format>", "Output format: json|table", "json")
|
|
62
72
|
.option("--limit <n>", "Limit results", "100")
|
|
63
73
|
.option("--offset <n>", "Skip results", "0")
|
|
64
|
-
.action(async (type, options) => {
|
|
65
|
-
|
|
66
|
-
});
|
|
74
|
+
.action(withExitCode(async (type, options) => {
|
|
75
|
+
return queryCommand(type, options);
|
|
76
|
+
}));
|
|
67
77
|
program
|
|
68
78
|
.command("search [query]")
|
|
69
79
|
.description("Search knowledge base metadata and markdown content")
|
|
@@ -130,9 +140,9 @@ program
|
|
|
130
140
|
.option("--staged", "Run check only against staged changes (experimental)")
|
|
131
141
|
.option("--min-links <n>", "Minimum number of links required for symbol coverage", "1")
|
|
132
142
|
.option("--dry-run", "Do not modify files; only print what would happen")
|
|
133
|
-
.action(async (options) => {
|
|
134
|
-
|
|
135
|
-
});
|
|
143
|
+
.action(withExitCode(async (options) => {
|
|
144
|
+
return checkCommand(options);
|
|
145
|
+
}));
|
|
136
146
|
program
|
|
137
147
|
.command("gc")
|
|
138
148
|
.description("Garbage collect stale branch KBs")
|
|
@@ -145,9 +155,7 @@ program
|
|
|
145
155
|
program
|
|
146
156
|
.command("doctor")
|
|
147
157
|
.description("Diagnose KB setup and configuration")
|
|
148
|
-
.action(async () =>
|
|
149
|
-
await doctorCommand();
|
|
150
|
-
});
|
|
158
|
+
.action(withExitCode(async () => doctorCommand()));
|
|
151
159
|
program
|
|
152
160
|
.command("branch")
|
|
153
161
|
.description("Manage branch KBs")
|
|
@@ -158,4 +166,11 @@ program
|
|
|
158
166
|
await branchEnsureCommand(options);
|
|
159
167
|
}
|
|
160
168
|
});
|
|
161
|
-
program
|
|
169
|
+
program
|
|
170
|
+
.parseAsync(process.argv)
|
|
171
|
+
.then(() => process.exit(process.exitCode ?? 0))
|
|
172
|
+
.catch((error) => {
|
|
173
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
174
|
+
console.error(message);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
});
|
package/dist/commands/check.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type Violation } from "../utils/rule-registry.js";
|
|
2
|
+
export type { Violation };
|
|
1
3
|
export interface CheckOptions {
|
|
2
4
|
fix?: boolean;
|
|
3
5
|
kbPath?: string;
|
|
@@ -6,12 +8,7 @@ export interface CheckOptions {
|
|
|
6
8
|
minLinks?: string | number;
|
|
7
9
|
dryRun?: boolean;
|
|
8
10
|
}
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
description: string;
|
|
13
|
-
suggestion?: string;
|
|
14
|
-
source?: string;
|
|
15
|
-
}
|
|
16
|
-
export declare function checkCommand(options: CheckOptions): Promise<void>;
|
|
11
|
+
export declare function checkCommand(options: CheckOptions): Promise<{
|
|
12
|
+
exitCode: number;
|
|
13
|
+
}>;
|
|
17
14
|
//# sourceMappingURL=check.d.ts.map
|
|
@@ -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":"AA4CA,OAAO,EAGL,KAAK,SAAS,EAEf,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,SAAS,EAAE,CAAC;AAK1B,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;AAGD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA0R/B"}
|
package/dist/commands/check.js
CHANGED
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
import * as path from "node:path";
|
|
19
19
|
import { extractFromManifest } from "../extractors/manifest.js";
|
|
20
20
|
import { PrologProcess } from "../prolog.js";
|
|
21
|
-
import { escapeAtom } from "../prolog/codec.js";
|
|
21
|
+
import { escapeAtom, parseTriples, parseViolationRows, } from "../prolog/codec.js";
|
|
22
22
|
import { getStagedFiles } from "../traceability/git-staged.js";
|
|
23
23
|
import { validateStagedMarkdown } from "../traceability/markdown-validate.js";
|
|
24
24
|
import { extractSymbolsFromStagedFile, } from "../traceability/symbol-extract.js";
|
|
25
25
|
import { cleanupTempKb, consultOverlay, createOverlayFacts, createTempKb, } from "../traceability/temp-kb.js";
|
|
26
26
|
import { formatViolations as formatStagedViolations, validateStagedSymbols, } from "../traceability/validate.js";
|
|
27
27
|
import { loadConfig } from "../utils/config.js";
|
|
28
|
+
import { safeCleanupProlog } from "../utils/prolog-cleanup.js";
|
|
28
29
|
import { RULES, getEffectiveRules, } from "../utils/rule-registry.js";
|
|
29
30
|
import { runAggregatedChecks } from "./aggregated-checks.js";
|
|
30
31
|
import { getCurrentBranch } from "./init-helpers.js";
|
|
@@ -83,7 +84,7 @@ export async function checkCommand(options) {
|
|
|
83
84
|
const stagedFiles = getStagedFiles();
|
|
84
85
|
if (!stagedFiles || stagedFiles.length === 0) {
|
|
85
86
|
console.log("No staged files found.");
|
|
86
|
-
|
|
87
|
+
return { exitCode: 0 };
|
|
87
88
|
}
|
|
88
89
|
const codeFiles = stagedFiles.filter((f) => !f.path.endsWith(".md"));
|
|
89
90
|
const markdownFiles = stagedFiles.filter((f) => f.path.endsWith(".md"));
|
|
@@ -101,9 +102,9 @@ export async function checkCommand(options) {
|
|
|
101
102
|
console.log();
|
|
102
103
|
}
|
|
103
104
|
if (options.dryRun) {
|
|
104
|
-
|
|
105
|
+
return { exitCode: 0 };
|
|
105
106
|
}
|
|
106
|
-
|
|
107
|
+
return { exitCode: 1 };
|
|
107
108
|
}
|
|
108
109
|
const allSymbols = [];
|
|
109
110
|
for (const f of codeFiles) {
|
|
@@ -119,11 +120,11 @@ export async function checkCommand(options) {
|
|
|
119
120
|
}
|
|
120
121
|
if (allSymbols.length === 0 && markdownFiles.length === 0) {
|
|
121
122
|
console.log("No exported symbols or markdown entities found in staged files.");
|
|
122
|
-
|
|
123
|
+
return { exitCode: 0 };
|
|
123
124
|
}
|
|
124
125
|
if (allSymbols.length === 0) {
|
|
125
126
|
console.log("✓ No violations found in staged files.");
|
|
126
|
-
|
|
127
|
+
return { exitCode: 0 };
|
|
127
128
|
}
|
|
128
129
|
// Create temp KB
|
|
129
130
|
tempCtx = await createTempKb(resolvedKbPath);
|
|
@@ -140,13 +141,13 @@ export async function checkCommand(options) {
|
|
|
140
141
|
console.log(violationsFormatted);
|
|
141
142
|
await cleanupTempKb(tempCtx.tempDir);
|
|
142
143
|
if (options.dryRun) {
|
|
143
|
-
|
|
144
|
+
return { exitCode: 0 };
|
|
144
145
|
}
|
|
145
|
-
|
|
146
|
+
return { exitCode: 1 };
|
|
146
147
|
}
|
|
147
148
|
console.log("✓ No violations found in staged symbols.");
|
|
148
149
|
await cleanupTempKb(tempCtx.tempDir);
|
|
149
|
-
|
|
150
|
+
return { exitCode: 0 };
|
|
150
151
|
}
|
|
151
152
|
catch (err) {
|
|
152
153
|
console.error(`Error running staged validation: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -154,9 +155,11 @@ export async function checkCommand(options) {
|
|
|
154
155
|
try {
|
|
155
156
|
await cleanupTempKb(tempCtx.tempDir);
|
|
156
157
|
}
|
|
157
|
-
catch {
|
|
158
|
+
catch {
|
|
159
|
+
// best-effort: temp directory may already be cleaned up
|
|
160
|
+
}
|
|
158
161
|
}
|
|
159
|
-
|
|
162
|
+
return { exitCode: 1 };
|
|
160
163
|
}
|
|
161
164
|
}
|
|
162
165
|
prolog = new PrologProcess({ timeout: 120000 });
|
|
@@ -166,7 +169,7 @@ export async function checkCommand(options) {
|
|
|
166
169
|
if (!attachResult.success) {
|
|
167
170
|
await prolog.terminate();
|
|
168
171
|
console.error(`Error: Failed to attach KB: ${attachResult.error}`);
|
|
169
|
-
|
|
172
|
+
return { exitCode: 1 };
|
|
170
173
|
}
|
|
171
174
|
attached = true;
|
|
172
175
|
const violations = [];
|
|
@@ -203,6 +206,7 @@ export async function checkCommand(options) {
|
|
|
203
206
|
"required-fields",
|
|
204
207
|
"deprecated-adr-no-successor",
|
|
205
208
|
"domain-contradictions",
|
|
209
|
+
"strict-fact-shape",
|
|
206
210
|
];
|
|
207
211
|
const canUseAggregated = Array.from(effectiveRules).every((r) => supportedRules.includes(r));
|
|
208
212
|
if (canUseAggregated) {
|
|
@@ -225,10 +229,11 @@ export async function checkCommand(options) {
|
|
|
225
229
|
}
|
|
226
230
|
await runCheck("deprecated-adr-no-successor", checkDeprecatedAdrs);
|
|
227
231
|
await runCheck("domain-contradictions", checkDomainContradictions);
|
|
232
|
+
await runCheck("strict-fact-shape", checkStrictFactShape);
|
|
228
233
|
}
|
|
229
234
|
if (violations.length === 0) {
|
|
230
235
|
console.log("✓ No violations found. KB is valid.");
|
|
231
|
-
|
|
236
|
+
return { exitCode: 0 };
|
|
232
237
|
}
|
|
233
238
|
console.log(`Found ${violations.length} violation(s):`);
|
|
234
239
|
console.log();
|
|
@@ -241,26 +246,15 @@ export async function checkCommand(options) {
|
|
|
241
246
|
}
|
|
242
247
|
console.log();
|
|
243
248
|
}
|
|
244
|
-
|
|
249
|
+
return { exitCode: 1 };
|
|
245
250
|
}
|
|
246
251
|
catch (error) {
|
|
247
252
|
const message = error instanceof Error ? error.message : String(error);
|
|
248
253
|
console.error(`Error: ${message}`);
|
|
249
|
-
|
|
254
|
+
return { exitCode: 1 };
|
|
250
255
|
}
|
|
251
256
|
finally {
|
|
252
|
-
|
|
253
|
-
if (attached) {
|
|
254
|
-
try {
|
|
255
|
-
await prolog.query("kb_detach");
|
|
256
|
-
}
|
|
257
|
-
catch { }
|
|
258
|
-
}
|
|
259
|
-
try {
|
|
260
|
-
await prolog.terminate();
|
|
261
|
-
}
|
|
262
|
-
catch { }
|
|
263
|
-
}
|
|
257
|
+
await safeCleanupProlog(prolog);
|
|
264
258
|
}
|
|
265
259
|
}
|
|
266
260
|
async function checkMustPriorityCoverage(prolog) {
|
|
@@ -545,7 +539,7 @@ async function checkDomainContradictions(prolog) {
|
|
|
545
539
|
if (!result.success || !result.bindings.Rows) {
|
|
546
540
|
return violations;
|
|
547
541
|
}
|
|
548
|
-
const rows =
|
|
542
|
+
const rows = parseTriples(result.bindings.Rows);
|
|
549
543
|
for (const [reqA, reqB, reason] of rows) {
|
|
550
544
|
violations.push({
|
|
551
545
|
rule: "domain-contradictions",
|
|
@@ -556,6 +550,22 @@ async function checkDomainContradictions(prolog) {
|
|
|
556
550
|
}
|
|
557
551
|
return violations;
|
|
558
552
|
}
|
|
553
|
+
async function checkStrictFactShape(prolog) {
|
|
554
|
+
const violations = [];
|
|
555
|
+
const result = await prolog.query(`findall(violation(Rule, EntityId, Desc, Sugg, Src),
|
|
556
|
+
checks:strict_fact_shape_violation(violation(Rule, EntityId, Desc, Sugg, Src)),
|
|
557
|
+
Violations)`);
|
|
558
|
+
if (!result.success || !result.bindings.Violations) {
|
|
559
|
+
return violations;
|
|
560
|
+
}
|
|
561
|
+
const violationsStr = result.bindings.Violations;
|
|
562
|
+
if (violationsStr && violationsStr !== "[]") {
|
|
563
|
+
for (const v of parseViolationRows(violationsStr)) {
|
|
564
|
+
violations.push(v);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return violations;
|
|
568
|
+
}
|
|
559
569
|
async function checkSymbolCoverage(prolog) {
|
|
560
570
|
const violations = [];
|
|
561
571
|
const uncoveredResult = await prolog.query("setof(Symbol, symbol_no_req_coverage(Symbol, _), Symbols)");
|
|
@@ -591,40 +601,9 @@ async function checkSymbolTraceability(prolog, requireAdr) {
|
|
|
591
601
|
}
|
|
592
602
|
const violationsStr = result.bindings.Violations;
|
|
593
603
|
if (violationsStr && violationsStr !== "[]") {
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
match = violationRegex.exec(violationsStr);
|
|
598
|
-
if (match) {
|
|
599
|
-
violations.push({
|
|
600
|
-
rule: match[1].trim().replace(/^'|'$/g, ""),
|
|
601
|
-
entityId: match[2].trim(),
|
|
602
|
-
description: match[3].trim().replace(/^"|"$/g, ""),
|
|
603
|
-
suggestion: match[4].trim().replace(/^"|"$/g, ""),
|
|
604
|
-
source: match[5].trim() || undefined,
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
} while (match);
|
|
604
|
+
for (const v of parseViolationRows(violationsStr)) {
|
|
605
|
+
violations.push(v);
|
|
606
|
+
}
|
|
608
607
|
}
|
|
609
608
|
return violations;
|
|
610
609
|
}
|
|
611
|
-
function parseTripleRows(raw) {
|
|
612
|
-
const cleaned = raw.trim();
|
|
613
|
-
if (cleaned === "[]" || cleaned.length === 0) {
|
|
614
|
-
return [];
|
|
615
|
-
}
|
|
616
|
-
const rows = [];
|
|
617
|
-
const rowRegex = /\[([^,]+),([^,]+),([^\]]+)\]/g;
|
|
618
|
-
let match;
|
|
619
|
-
do {
|
|
620
|
-
match = rowRegex.exec(cleaned);
|
|
621
|
-
if (match) {
|
|
622
|
-
rows.push([
|
|
623
|
-
match[1].trim().replace(/^'|'$/g, ""),
|
|
624
|
-
match[2].trim().replace(/^'|'$/g, ""),
|
|
625
|
-
match[3].trim().replace(/^'|'$/g, ""),
|
|
626
|
-
]);
|
|
627
|
-
}
|
|
628
|
-
} while (match);
|
|
629
|
-
return rows;
|
|
630
|
-
}
|
|
@@ -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;
|
|
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"}
|
|
@@ -2,6 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import Table from "cli-table3";
|
|
3
3
|
import { PrologProcess, resolveKbPlPath } from "../prolog.js";
|
|
4
4
|
import { escapeAtom } from "../prolog/codec.js";
|
|
5
|
+
import { safeCleanupProlog } from "../utils/prolog-cleanup.js";
|
|
5
6
|
import { getCurrentBranch } from "./init-helpers.js";
|
|
6
7
|
// implements REQ-003
|
|
7
8
|
export async function withAttachedBranchProlog(callback) {
|
|
@@ -13,7 +14,8 @@ export async function withAttachedBranchProlog(callback) {
|
|
|
13
14
|
await prolog.query("set_prolog_flag(answer_write_options, [max_depth(0), spacing(next_argument)])");
|
|
14
15
|
let branch;
|
|
15
16
|
try {
|
|
16
|
-
branch =
|
|
17
|
+
branch =
|
|
18
|
+
process.env.KIBI_BRANCH || (await getCurrentBranch(process.cwd()));
|
|
17
19
|
}
|
|
18
20
|
catch {
|
|
19
21
|
branch = process.env.KIBI_BRANCH || "main";
|
|
@@ -27,18 +29,7 @@ export async function withAttachedBranchProlog(callback) {
|
|
|
27
29
|
return await callback(prolog);
|
|
28
30
|
}
|
|
29
31
|
finally {
|
|
30
|
-
|
|
31
|
-
if (attached) {
|
|
32
|
-
try {
|
|
33
|
-
await prolog.query("kb_detach");
|
|
34
|
-
}
|
|
35
|
-
catch { }
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
await prolog.terminate();
|
|
39
|
-
}
|
|
40
|
-
catch { }
|
|
41
|
-
}
|
|
32
|
+
await safeCleanupProlog(prolog);
|
|
42
33
|
}
|
|
43
34
|
}
|
|
44
35
|
// implements REQ-003
|
|
@@ -46,16 +37,12 @@ export async function withPrologProcess(callback) {
|
|
|
46
37
|
const prolog = new PrologProcess({ timeout: 120000 });
|
|
47
38
|
try {
|
|
48
39
|
await prolog.start();
|
|
49
|
-
;
|
|
50
40
|
prolog.useOneShotMode = true;
|
|
51
41
|
await prolog.query("set_prolog_flag(answer_write_options, [max_depth(0), spacing(next_argument)])");
|
|
52
42
|
return await callback(prolog);
|
|
53
43
|
}
|
|
54
44
|
finally {
|
|
55
|
-
|
|
56
|
-
await prolog.terminate();
|
|
57
|
-
}
|
|
58
|
-
catch { }
|
|
45
|
+
await safeCleanupProlog(prolog);
|
|
59
46
|
}
|
|
60
47
|
}
|
|
61
48
|
// implements REQ-003
|
|
@@ -110,13 +97,16 @@ function renderDiscoveryTable(structured) {
|
|
|
110
97
|
if (Array.isArray(payload.results)) {
|
|
111
98
|
return renderSearchTable(payload);
|
|
112
99
|
}
|
|
113
|
-
if (typeof payload.branch === "string" &&
|
|
100
|
+
if (typeof payload.branch === "string" &&
|
|
101
|
+
typeof payload.syncState === "string") {
|
|
114
102
|
return renderStatusTable(payload);
|
|
115
103
|
}
|
|
116
104
|
if (Array.isArray(payload.nodes) && Array.isArray(payload.edges)) {
|
|
117
105
|
return renderGraphTable(payload);
|
|
118
106
|
}
|
|
119
|
-
if (Array.isArray(payload.rows) &&
|
|
107
|
+
if (Array.isArray(payload.rows) &&
|
|
108
|
+
payload.summary &&
|
|
109
|
+
typeof payload.summary === "object") {
|
|
120
110
|
return renderCoverageTable(payload);
|
|
121
111
|
}
|
|
122
112
|
if (Array.isArray(payload.rows)) {
|
|
@@ -134,7 +124,9 @@ function renderSearchTable(payload) {
|
|
|
134
124
|
for (const row of rows) {
|
|
135
125
|
const match = row;
|
|
136
126
|
const entity = (match.entity ?? {});
|
|
137
|
-
const reasons = Array.isArray(match.reasons)
|
|
127
|
+
const reasons = Array.isArray(match.reasons)
|
|
128
|
+
? match.reasons.join(", ")
|
|
129
|
+
: "";
|
|
138
130
|
table.push([
|
|
139
131
|
stringifyCell(entity.id),
|
|
140
132
|
stringifyCell(entity.type),
|
|
@@ -192,7 +184,16 @@ function renderCoverageTable(payload) {
|
|
|
192
184
|
const isRequirementCoverage = firstRow && Object.hasOwn(firstRow, "scenarioCount");
|
|
193
185
|
const table = isRequirementCoverage
|
|
194
186
|
? new Table({
|
|
195
|
-
head: [
|
|
187
|
+
head: [
|
|
188
|
+
"ID",
|
|
189
|
+
"Status",
|
|
190
|
+
"Priority",
|
|
191
|
+
"Coverage",
|
|
192
|
+
"Scen",
|
|
193
|
+
"Tests",
|
|
194
|
+
"Symbols",
|
|
195
|
+
"Gaps",
|
|
196
|
+
],
|
|
196
197
|
colWidths: [20, 12, 12, 18, 8, 8, 10, 28],
|
|
197
198
|
wordWrap: true,
|
|
198
199
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AA4BA,wBAAsB,aAAa,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAyDnE"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import { execSync } from "node:child_process";
|
|
19
19
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
20
20
|
import * as path from "node:path";
|
|
21
|
+
// implements REQ-003
|
|
21
22
|
export async function doctorCommand() {
|
|
22
23
|
const checks = [
|
|
23
24
|
{
|
|
@@ -65,12 +66,10 @@ export async function doctorCommand() {
|
|
|
65
66
|
console.log();
|
|
66
67
|
if (allPassed) {
|
|
67
68
|
console.log("All checks passed! Your environment is ready.");
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
console.log("Some checks failed. Please address the issues above.");
|
|
72
|
-
process.exit(1);
|
|
69
|
+
return { exitCode: 0 };
|
|
73
70
|
}
|
|
71
|
+
console.log("Some checks failed. Please address the issues above.");
|
|
72
|
+
return { exitCode: 1 };
|
|
74
73
|
}
|
|
75
74
|
function checkSWIProlog() {
|
|
76
75
|
try {
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
interface InitOptions {
|
|
2
2
|
hooks?: boolean;
|
|
3
3
|
}
|
|
4
|
-
export declare function initCommand(options: InitOptions): Promise<
|
|
4
|
+
export declare function initCommand(options: InitOptions): Promise<{
|
|
5
|
+
exitCode: number;
|
|
6
|
+
}>;
|
|
5
7
|
export {};
|
|
6
8
|
//# sourceMappingURL=init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAiCA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAiCA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAGD,wBAAsB,WAAW,CAC/B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA6D/B"}
|
package/dist/commands/init.js
CHANGED
|
@@ -22,6 +22,7 @@ import { resolveActiveBranch } from "../utils/branch-resolver.js";
|
|
|
22
22
|
import { copySchemaFiles, createConfigFile, createKbDirectoryStructure, installGitHooks, updateGitIgnore, } from "./init-helpers.js";
|
|
23
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
24
24
|
const __dirname = path.dirname(__filename);
|
|
25
|
+
// implements REQ-003
|
|
25
26
|
export async function initCommand(options) {
|
|
26
27
|
const kbDir = path.join(process.cwd(), ".kb");
|
|
27
28
|
const kbExists = existsSync(kbDir);
|
|
@@ -40,7 +41,7 @@ export async function initCommand(options) {
|
|
|
40
41
|
else {
|
|
41
42
|
console.error("Error: Failed to resolve the active git branch.");
|
|
42
43
|
console.error(result.error);
|
|
43
|
-
|
|
44
|
+
return { exitCode: 1 };
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
else {
|
|
@@ -70,10 +71,10 @@ export async function initCommand(options) {
|
|
|
70
71
|
console.log("Next steps:");
|
|
71
72
|
console.log(" 1. Run 'kibi doctor' to verify setup");
|
|
72
73
|
console.log(" 2. Run 'kibi sync' to extract entities from documents");
|
|
73
|
-
|
|
74
|
+
return { exitCode: 0 };
|
|
74
75
|
}
|
|
75
76
|
catch (error) {
|
|
76
77
|
console.error("Error during initialization:", error);
|
|
77
|
-
|
|
78
|
+
return { exitCode: 1 };
|
|
78
79
|
}
|
|
79
80
|
}
|
package/dist/commands/query.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ interface QueryOptions {
|
|
|
7
7
|
limit?: string;
|
|
8
8
|
offset?: string;
|
|
9
9
|
}
|
|
10
|
-
export declare function queryCommand(type: string | undefined, options: QueryOptions): Promise<
|
|
10
|
+
export declare function queryCommand(type: string | undefined, options: QueryOptions): Promise<{
|
|
11
|
+
exitCode: number;
|
|
12
|
+
}>;
|
|
11
13
|
export {};
|
|
12
14
|
//# sourceMappingURL=query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/commands/query.js
CHANGED
|
@@ -22,6 +22,7 @@ import { parseEntityFromBinding, parseEntityFromList, parseListOfLists, parsePro
|
|
|
22
22
|
import relationshipSchema from "../public/schemas/relationship.js";
|
|
23
23
|
import { VALID_ENTITY_TYPES } from "../query/service.js";
|
|
24
24
|
import { resolveActiveBranch } from "../utils/branch-resolver.js";
|
|
25
|
+
import { safeCleanupProlog } from "../utils/prolog-cleanup.js";
|
|
25
26
|
const REL_TYPES = relationshipSchema.properties.type.enum;
|
|
26
27
|
// implements REQ-003
|
|
27
28
|
export async function queryCommand(type, options) {
|
|
@@ -45,7 +46,7 @@ export async function queryCommand(type, options) {
|
|
|
45
46
|
else {
|
|
46
47
|
console.error(`Error: Failed to resolve active branch:\n${branchResult.error}`);
|
|
47
48
|
await prolog.terminate();
|
|
48
|
-
|
|
49
|
+
return { exitCode: 1 };
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
else {
|
|
@@ -56,7 +57,7 @@ export async function queryCommand(type, options) {
|
|
|
56
57
|
if (!attachResult.success) {
|
|
57
58
|
await prolog.terminate();
|
|
58
59
|
console.error(`Error: Failed to attach KB: ${attachResult.error || "Unknown error"}`);
|
|
59
|
-
|
|
60
|
+
return { exitCode: 1 };
|
|
60
61
|
}
|
|
61
62
|
attached = true;
|
|
62
63
|
let results = [];
|
|
@@ -86,8 +87,7 @@ export async function queryCommand(type, options) {
|
|
|
86
87
|
else if (type || options.source) {
|
|
87
88
|
if (type && !VALID_ENTITY_TYPES.includes(type)) {
|
|
88
89
|
console.error(`Error: Invalid type '${type}'. Valid types: ${VALID_ENTITY_TYPES.join(", ")}`);
|
|
89
|
-
|
|
90
|
-
return;
|
|
90
|
+
return { exitCode: 1 };
|
|
91
91
|
}
|
|
92
92
|
let goal;
|
|
93
93
|
if (options.source) {
|
|
@@ -133,8 +133,7 @@ export async function queryCommand(type, options) {
|
|
|
133
133
|
}
|
|
134
134
|
else {
|
|
135
135
|
console.error("Error: Must specify entity type, --source, or --relationships option");
|
|
136
|
-
|
|
137
|
-
return;
|
|
136
|
+
return { exitCode: 1 };
|
|
138
137
|
}
|
|
139
138
|
const limit = Number.parseInt(options.limit || "100");
|
|
140
139
|
const offset = Number.parseInt(options.offset || "0");
|
|
@@ -146,7 +145,7 @@ export async function queryCommand(type, options) {
|
|
|
146
145
|
else {
|
|
147
146
|
console.log("No entities found");
|
|
148
147
|
}
|
|
149
|
-
return;
|
|
148
|
+
return { exitCode: 0 };
|
|
150
149
|
}
|
|
151
150
|
// Format output
|
|
152
151
|
if (options.format === "table") {
|
|
@@ -155,25 +154,15 @@ export async function queryCommand(type, options) {
|
|
|
155
154
|
else {
|
|
156
155
|
console.log(JSON.stringify(paginated, null, 2));
|
|
157
156
|
}
|
|
157
|
+
return { exitCode: 0 };
|
|
158
158
|
}
|
|
159
159
|
catch (error) {
|
|
160
160
|
const message = error instanceof Error ? error.message : String(error);
|
|
161
161
|
console.error(`Error: ${message}`);
|
|
162
|
-
|
|
162
|
+
return { exitCode: 1 };
|
|
163
163
|
}
|
|
164
164
|
finally {
|
|
165
|
-
|
|
166
|
-
if (attached) {
|
|
167
|
-
try {
|
|
168
|
-
await prolog.query("kb_detach");
|
|
169
|
-
}
|
|
170
|
-
catch { }
|
|
171
|
-
}
|
|
172
|
-
try {
|
|
173
|
-
await prolog.terminate();
|
|
174
|
-
}
|
|
175
|
-
catch { }
|
|
176
|
-
}
|
|
165
|
+
await safeCleanupProlog(prolog);
|
|
177
166
|
}
|
|
178
167
|
}
|
|
179
168
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AASA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAGD,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|
package/dist/commands/search.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { VALID_ENTITY_TYPES, queryEntities } from "../query/service.js";
|
|
1
2
|
import { rankEntities } from "../search-ranking.js";
|
|
2
|
-
import { VALID_ENTITY_TYPES, queryEntities, } from "../query/service.js";
|
|
3
3
|
import { printDiscoveryResult, withAttachedBranchProlog, } from "./discovery-shared.js";
|
|
4
4
|
// implements REQ-mcp-search-discovery, REQ-003
|
|
5
5
|
export async function searchCommand(query, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/persistence.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/persistence.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAEV,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAqErD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAsB,eAAe,CAEnC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GACrB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC,CAoEvD;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,kBAAkB,EAAE,qBAAqB,EAAE,GAC1C,OAAO,CAAC;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC,CAiI7D"}
|