kibi-cli 0.12.1 → 0.12.4
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/check.d.ts.map +1 -1
- package/dist/commands/check.js +7 -3
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +4 -2
- package/dist/commands/usage-metrics.d.ts.map +1 -1
- package/dist/commands/usage-metrics.js +60 -0
- package/dist/extractors/symbols-coordinator.d.ts +1 -1
- package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
- package/dist/extractors/symbols-ts.js +36 -2
- package/dist/prolog.d.ts +3 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +43 -18
- package/dist/public/skills/kibi-usage/SKILL.md +4 -0
- package/dist/traceability/symbol-extract.d.ts +1 -1
- package/dist/traceability/symbol-extract.d.ts.map +1 -1
- package/dist/traceability/symbol-extract.js +31 -6
- package/package.json +2 -8
- package/src/public/skills/kibi-usage/SKILL.md +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AA2EA,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;
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AA2EA,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;AAgcD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA0V/B"}
|
package/dist/commands/check.js
CHANGED
|
@@ -101,7 +101,9 @@ function buildManifestLookup(stagedFiles) {
|
|
|
101
101
|
const authoredSymbolResult = {
|
|
102
102
|
entity: entry.entity,
|
|
103
103
|
relationships: entry.relationships,
|
|
104
|
-
...(entry.sourceFile !== undefined
|
|
104
|
+
...(entry.sourceFile !== undefined
|
|
105
|
+
? { sourceFile: entry.sourceFile }
|
|
106
|
+
: {}),
|
|
105
107
|
};
|
|
106
108
|
authoredSymbolResults.push(authoredSymbolResult);
|
|
107
109
|
stagedAuthoredSymbolResults.push(authoredSymbolResult);
|
|
@@ -147,7 +149,7 @@ function hasTraceabilityRelationship(result) {
|
|
|
147
149
|
}
|
|
148
150
|
function hasValidGranularityReason(result) {
|
|
149
151
|
const reason = result.entity.granularity_reason;
|
|
150
|
-
return
|
|
152
|
+
return typeof reason === "string" && ALLOWED_GRANULARITY_REASONS.has(reason);
|
|
151
153
|
}
|
|
152
154
|
function createSymbolGranularityDiagnostics(options) {
|
|
153
155
|
const diagnostics = [];
|
|
@@ -161,7 +163,9 @@ function createSymbolGranularityDiagnostics(options) {
|
|
|
161
163
|
const granularSymbols = getGranularSymbolsForSourceFile(result.sourceFile, options.symbolsByFile, options.sourceContentByFile);
|
|
162
164
|
if (granularSymbols.length === 0)
|
|
163
165
|
continue;
|
|
164
|
-
const granularNames = [
|
|
166
|
+
const granularNames = [
|
|
167
|
+
...new Set(granularSymbols.map((s) => s.name)),
|
|
168
|
+
].sort();
|
|
165
169
|
if (granularNames.includes(result.entity.title))
|
|
166
170
|
continue;
|
|
167
171
|
diagnostics.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAqCA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAqCA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAiWD,wBAAsB,cAAc,CAClC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgI/B"}
|
package/dist/commands/migrate.js
CHANGED
|
@@ -135,7 +135,7 @@ function hasTraceabilityRelationship(symbol) {
|
|
|
135
135
|
return false;
|
|
136
136
|
}
|
|
137
137
|
const type = relationship.type;
|
|
138
|
-
return typeof type === "string" && TRACEABILITY_RELATIONSHIP_TYPES.has(type);
|
|
138
|
+
return (typeof type === "string" && TRACEABILITY_RELATIONSHIP_TYPES.has(type));
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
function getGranularNames(cwd, sourceFile) {
|
|
@@ -218,7 +218,9 @@ function migrateSymbolGranularity(options) {
|
|
|
218
218
|
const migratedSymbolIds = new Set();
|
|
219
219
|
const granularNamesByFile = new Map();
|
|
220
220
|
for (const symbol of manifest.symbols) {
|
|
221
|
-
if (symbol === null ||
|
|
221
|
+
if (symbol === null ||
|
|
222
|
+
typeof symbol !== "object" ||
|
|
223
|
+
Array.isArray(symbol)) {
|
|
222
224
|
continue;
|
|
223
225
|
}
|
|
224
226
|
const record = symbol;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-metrics.d.ts","sourceRoot":"","sources":["../../src/commands/usage-metrics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"usage-metrics.d.ts","sourceRoot":"","sources":["../../src/commands/usage-metrics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAyED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAuBpC"}
|
|
@@ -54,6 +54,9 @@ function buildUsageMetricsReport(rows, limit) {
|
|
|
54
54
|
const zeroResultToolCounts = new Map();
|
|
55
55
|
const zeroResultSourceFileCounts = new Map();
|
|
56
56
|
const upsertErrorCategories = new Map();
|
|
57
|
+
const errorCategories = new Map();
|
|
58
|
+
const errorStages = new Map();
|
|
59
|
+
const errorsByTool = new Map();
|
|
57
60
|
const violationTrend = [];
|
|
58
61
|
let successCount = 0;
|
|
59
62
|
let errorCount = 0;
|
|
@@ -69,6 +72,10 @@ function buildUsageMetricsReport(rows, limit) {
|
|
|
69
72
|
}
|
|
70
73
|
if (outcome === "error") {
|
|
71
74
|
errorCount += 1;
|
|
75
|
+
const category = row.error_category ?? categorizeError(row.error_message ?? row.error);
|
|
76
|
+
increment(errorCategories, category);
|
|
77
|
+
increment(errorStages, row.error_stage ?? inferErrorStage(row.error_message ?? row.error));
|
|
78
|
+
increment(errorsByTool, normalizeKey(row.tool, "unknown"));
|
|
72
79
|
}
|
|
73
80
|
if (hasCompleteTelemetry(row)) {
|
|
74
81
|
telemetryCompleteCount += 1;
|
|
@@ -128,6 +135,11 @@ function buildUsageMetricsReport(rows, limit) {
|
|
|
128
135
|
upsertErrors: {
|
|
129
136
|
categories: mapToSortedObject(upsertErrorCategories),
|
|
130
137
|
},
|
|
138
|
+
errors: {
|
|
139
|
+
categories: mapToSortedObject(errorCategories),
|
|
140
|
+
stages: mapToSortedObject(errorStages),
|
|
141
|
+
byTool: mapToSortedObject(errorsByTool),
|
|
142
|
+
},
|
|
131
143
|
};
|
|
132
144
|
}
|
|
133
145
|
function hasCompleteTelemetry(row) {
|
|
@@ -180,9 +192,31 @@ function getSourceFile(row) {
|
|
|
180
192
|
return null;
|
|
181
193
|
}
|
|
182
194
|
function categorizeUpsertError(errorMessage) {
|
|
195
|
+
return categorizeError(errorMessage);
|
|
196
|
+
}
|
|
197
|
+
function categorizeError(errorMessage) {
|
|
183
198
|
if (!errorMessage) {
|
|
184
199
|
return "Unknown error";
|
|
185
200
|
}
|
|
201
|
+
const lower = errorMessage.toLowerCase();
|
|
202
|
+
if (lower.includes("stale_snapshot")) {
|
|
203
|
+
return "stale_snapshot";
|
|
204
|
+
}
|
|
205
|
+
if (lower.includes("unknown option") && lower.includes("h for help")) {
|
|
206
|
+
return "prolog_unknown_option";
|
|
207
|
+
}
|
|
208
|
+
if (lower.includes("prolog process not started")) {
|
|
209
|
+
return "prolog_process_not_started";
|
|
210
|
+
}
|
|
211
|
+
if (lower.includes("coarsely while granular symbols are available")) {
|
|
212
|
+
return "coarse_symbol_linkage";
|
|
213
|
+
}
|
|
214
|
+
if (lower.includes("module load failed")) {
|
|
215
|
+
return "prolog_module_load_failed";
|
|
216
|
+
}
|
|
217
|
+
if (lower.includes("query failed")) {
|
|
218
|
+
return "prolog_query_failed";
|
|
219
|
+
}
|
|
186
220
|
if (errorMessage.startsWith("Entity validation failed:")) {
|
|
187
221
|
return "Entity validation failed";
|
|
188
222
|
}
|
|
@@ -199,6 +233,29 @@ function categorizeUpsertError(errorMessage) {
|
|
|
199
233
|
}
|
|
200
234
|
return errorMessage.trim() || "Unknown error";
|
|
201
235
|
}
|
|
236
|
+
function inferErrorStage(errorMessage) {
|
|
237
|
+
if (!errorMessage) {
|
|
238
|
+
return "unknown";
|
|
239
|
+
}
|
|
240
|
+
const lower = errorMessage.toLowerCase();
|
|
241
|
+
if (lower.includes("stale_snapshot")) {
|
|
242
|
+
return "persistence";
|
|
243
|
+
}
|
|
244
|
+
if (lower.includes("unknown option") ||
|
|
245
|
+
lower.includes("module load failed") ||
|
|
246
|
+
lower.includes("query failed")) {
|
|
247
|
+
return "prolog_runtime";
|
|
248
|
+
}
|
|
249
|
+
if (lower.includes("prolog process not started")) {
|
|
250
|
+
return "prolog_lifecycle";
|
|
251
|
+
}
|
|
252
|
+
if (lower.includes("validation failed") ||
|
|
253
|
+
lower.includes("relationship source must match") ||
|
|
254
|
+
lower.includes("coarsely while granular symbols are available")) {
|
|
255
|
+
return "validation";
|
|
256
|
+
}
|
|
257
|
+
return "unknown";
|
|
258
|
+
}
|
|
202
259
|
function increment(counts, key) {
|
|
203
260
|
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
204
261
|
}
|
|
@@ -221,6 +278,9 @@ function renderUsageMetricsReport(report) {
|
|
|
221
278
|
renderZeroResultsTable(report),
|
|
222
279
|
renderViolationTrendTable(report),
|
|
223
280
|
renderCountsTable("Upsert Error Categories", "Category", report.upsertErrors.categories),
|
|
281
|
+
renderCountsTable("Error Categories", "Category", report.errors.categories),
|
|
282
|
+
renderCountsTable("Error Stages", "Stage", report.errors.stages),
|
|
283
|
+
renderCountsTable("Errors By Tool", "Tool", report.errors.byTool),
|
|
224
284
|
].filter(Boolean);
|
|
225
285
|
return sections.join("\n\n");
|
|
226
286
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ManifestSymbolEntry, enrichSymbolCoordinatesWithTsMorph } from "./symbols-ts.js";
|
|
2
2
|
export type { ManifestSymbolEntry };
|
|
3
3
|
export type SourceAnalysisMode = "parser" | "fallback";
|
|
4
|
-
export type SourceSymbolKind = "function" | "class" | "interface" | "type" | "enum" | "variable" | "unknown";
|
|
4
|
+
export type SourceSymbolKind = "function" | "class" | "method" | "interface" | "type" | "enum" | "variable" | "unknown";
|
|
5
5
|
export interface SourceSymbolAnalysis {
|
|
6
6
|
name: string;
|
|
7
7
|
kind: SourceSymbolKind;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbols-coordinator.d.ts","sourceRoot":"","sources":["../../src/extractors/symbols-coordinator.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,KAAK,mBAAmB,EAExB,kCAAkC,EACnC,MAAM,iBAAiB,CAAC;AAazB,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEvD,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,OAAO,GACP,WAAW,GACX,MAAM,GACN,MAAM,GACN,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,kBAAkB,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAAC;CACtE;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;CACtC;AAED,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,OAAO,kCAAkC,CAAC;CAChE;AA+BD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,mBAAmB,EAAE,EAC9B,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,GAC1C,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAClC,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,wBAAwB,GACjC,oBAAoB,CAAC;AAkCxB,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,mBAAmB,EAAE,EAC9B,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,GAC1C,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAqChC"}
|
|
1
|
+
{"version":3,"file":"symbols-coordinator.d.ts","sourceRoot":"","sources":["../../src/extractors/symbols-coordinator.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,KAAK,mBAAmB,EAExB,kCAAkC,EACnC,MAAM,iBAAiB,CAAC;AAazB,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEvD,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,OAAO,GACP,QAAQ,GACR,WAAW,GACX,MAAM,GACN,MAAM,GACN,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,kBAAkB,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAAC;CACtE;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;CACtC;AAED,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,OAAO,kCAAkC,CAAC;CAChE;AA+BD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,mBAAmB,EAAE,EAC9B,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,GAC1C,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAClC,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,wBAAwB,GACjC,oBAAoB,CAAC;AAkCxB,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,mBAAmB,EAAE,EAC9B,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,GAC1C,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAqChC"}
|
|
@@ -184,10 +184,16 @@ function collectSourceSymbols(sourceFile) {
|
|
|
184
184
|
for (const decl of sourceFile.getClasses()) {
|
|
185
185
|
if (!decl.isExported())
|
|
186
186
|
continue;
|
|
187
|
-
symbols.push(toSourceSymbolAnalysis(sourceFile, decl.getName() ?? "<anonymous>", "class", decl.getNameNode() ?? decl, decl,
|
|
187
|
+
symbols.push(toSourceSymbolAnalysis(sourceFile, decl.getName() ?? "<anonymous>", "class", decl.getNameNode() ?? decl, decl, decl
|
|
188
188
|
.getJsDocs()
|
|
189
189
|
.map((doc) => doc.getFullText())
|
|
190
|
-
.join("\n")
|
|
190
|
+
.join("\n")));
|
|
191
|
+
for (const method of decl.getMethods()) {
|
|
192
|
+
symbols.push(toSourceSymbolAnalysis(sourceFile, formatMethodSymbolName(decl.getName(), method.getName()), "method", method.getNameNode() ?? method, method, `${method.getFullText()}\n${method
|
|
193
|
+
.getJsDocs()
|
|
194
|
+
.map((doc) => doc.getFullText())
|
|
195
|
+
.join("\n")}`));
|
|
196
|
+
}
|
|
191
197
|
}
|
|
192
198
|
for (const decl of sourceFile.getInterfaces()) {
|
|
193
199
|
if (!decl.isExported())
|
|
@@ -226,6 +232,9 @@ function toSourceSymbolAnalysis(sourceFile, name, kind, startNode, endNode, dire
|
|
|
226
232
|
directiveText,
|
|
227
233
|
};
|
|
228
234
|
}
|
|
235
|
+
function formatMethodSymbolName(className, methodName) {
|
|
236
|
+
return className ? `${className}.${methodName}` : methodName;
|
|
237
|
+
}
|
|
229
238
|
function chooseScriptKind(filePath) {
|
|
230
239
|
const lower = filePath.toLowerCase();
|
|
231
240
|
if (lower.endsWith(".tsx"))
|
|
@@ -252,6 +261,22 @@ function inferModuleTitle(filePath) {
|
|
|
252
261
|
return basename.length > 0 ? basename : path.basename(filePath);
|
|
253
262
|
}
|
|
254
263
|
function findNamedDeclaration(sourceFile, title) {
|
|
264
|
+
const qualifiedMethod = parseQualifiedMethodTitle(title);
|
|
265
|
+
if (qualifiedMethod) {
|
|
266
|
+
for (const cls of sourceFile.getClasses()) {
|
|
267
|
+
if (cls.getName() !== qualifiedMethod.className)
|
|
268
|
+
continue;
|
|
269
|
+
for (const method of cls.getMethods()) {
|
|
270
|
+
if (method.getName() !== qualifiedMethod.methodName)
|
|
271
|
+
continue;
|
|
272
|
+
const nameNode = method.getNameNode();
|
|
273
|
+
if (!nameNode)
|
|
274
|
+
continue;
|
|
275
|
+
return { node: method, getNameNode: () => nameNode };
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
255
280
|
const candidates = [];
|
|
256
281
|
for (const decl of sourceFile.getFunctions()) {
|
|
257
282
|
if (!decl.isExported())
|
|
@@ -357,3 +382,12 @@ function findNamedDeclaration(sourceFile, title) {
|
|
|
357
382
|
candidates.sort((a, b) => a.getNameNode().getStart() - b.getNameNode().getStart());
|
|
358
383
|
return candidates[0] ?? null;
|
|
359
384
|
}
|
|
385
|
+
function parseQualifiedMethodTitle(title) {
|
|
386
|
+
const separatorIndex = title.lastIndexOf(".");
|
|
387
|
+
if (separatorIndex <= 0 || separatorIndex === title.length - 1)
|
|
388
|
+
return null;
|
|
389
|
+
return {
|
|
390
|
+
className: title.slice(0, separatorIndex),
|
|
391
|
+
methodName: title.slice(separatorIndex + 1),
|
|
392
|
+
};
|
|
393
|
+
}
|
package/dist/prolog.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class PrologProcess {
|
|
|
16
16
|
private errorBuffer;
|
|
17
17
|
private cache;
|
|
18
18
|
private interactiveQueryTail;
|
|
19
|
+
private terminationPromise;
|
|
19
20
|
private useOneShotMode;
|
|
20
21
|
private attachedKbPath;
|
|
21
22
|
private onProcessExit;
|
|
@@ -30,6 +31,8 @@ export declare class PrologProcess {
|
|
|
30
31
|
private queryOneShot;
|
|
31
32
|
private execOneShot;
|
|
32
33
|
private normalizeGoal;
|
|
34
|
+
private clearQueryBuffers;
|
|
35
|
+
private isProcessUsable;
|
|
33
36
|
private extractBindings;
|
|
34
37
|
private translateError;
|
|
35
38
|
isRunning(): boolean;
|
package/dist/prolog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prolog.d.ts","sourceRoot":"","sources":["../src/prolog.ts"],"names":[],"mappings":"AA4BA,wBAAgB,eAAe,IAAI,MAAM,CAsCxC;AACD,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,cAAc,CACyC;IAC/D,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,aAAa,CAA6B;gBAEtC,OAAO,GAAE,aAAkB;IAKjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"prolog.d.ts","sourceRoot":"","sources":["../src/prolog.ts"],"names":[],"mappings":"AA4BA,wBAAgB,eAAe,IAAI,MAAM,CAsCxC;AACD,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,kBAAkB,CAA8B;IACxD,OAAO,CAAC,cAAc,CACyC;IAC/D,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,aAAa,CAA6B;gBAEtC,OAAO,GAAE,aAAkB;IAKjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAuCd,YAAY;IA0CpB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAmK1D,eAAe,IAAI,IAAI;IAIvB,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,kBAAkB;YAIZ,YAAY;IA2C1B,OAAO,CAAC,WAAW;IAsGnB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,cAAc;IA+BtB,SAAS,IAAI,OAAO;IAMpB,MAAM,IAAI,MAAM;IAIV,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CAwCjC"}
|
package/dist/prolog.js
CHANGED
|
@@ -67,6 +67,7 @@ export class PrologProcess {
|
|
|
67
67
|
errorBuffer = "";
|
|
68
68
|
cache = new Map();
|
|
69
69
|
interactiveQueryTail = Promise.resolve();
|
|
70
|
+
terminationPromise = null;
|
|
70
71
|
useOneShotMode = typeof globalThis.Bun !== "undefined";
|
|
71
72
|
attachedKbPath = null;
|
|
72
73
|
onProcessExit = null;
|
|
@@ -84,6 +85,7 @@ export class PrologProcess {
|
|
|
84
85
|
`use_module('${kbPath}'), use_module(library(semweb/rdf_db)), set_prolog_flag(answer_write_options, [max_depth(0), quoted(true)])`,
|
|
85
86
|
"--quiet",
|
|
86
87
|
]);
|
|
88
|
+
this.clearQueryBuffers();
|
|
87
89
|
if (!this.process.stdout || !this.process.stderr || !this.process.stdin) {
|
|
88
90
|
throw new Error("Failed to spawn Prolog process");
|
|
89
91
|
}
|
|
@@ -155,12 +157,11 @@ export class PrologProcess {
|
|
|
155
157
|
const batchGoal = `(${goal.map((item) => this.normalizeGoal(item)).join(", ")})`;
|
|
156
158
|
return this.query(batchGoal);
|
|
157
159
|
}
|
|
158
|
-
if (!this.
|
|
160
|
+
if (!this.isProcessUsable()) {
|
|
159
161
|
throw new Error("Prolog process not started");
|
|
160
162
|
}
|
|
161
163
|
const runInteractiveQuery = async () => {
|
|
162
|
-
this.
|
|
163
|
-
this.errorBuffer = "";
|
|
164
|
+
this.clearQueryBuffers();
|
|
164
165
|
const debug = isPrologDebugEnabled();
|
|
165
166
|
const normalizedGoal = this.normalizeGoal(goal);
|
|
166
167
|
const wrappedGoal = /^once\s*\(/.test(normalizedGoal)
|
|
@@ -258,7 +259,7 @@ export class PrologProcess {
|
|
|
258
259
|
});
|
|
259
260
|
await previousQuery;
|
|
260
261
|
try {
|
|
261
|
-
if (!this.
|
|
262
|
+
if (!this.isProcessUsable()) {
|
|
262
263
|
throw new Error("Prolog process not started");
|
|
263
264
|
}
|
|
264
265
|
return await runInteractiveQuery();
|
|
@@ -410,6 +411,16 @@ export class PrologProcess {
|
|
|
410
411
|
normalizeGoal(goal) {
|
|
411
412
|
return goal.trim().replace(/\.+\s*$/, "");
|
|
412
413
|
}
|
|
414
|
+
clearQueryBuffers() {
|
|
415
|
+
this.outputBuffer = "";
|
|
416
|
+
this.errorBuffer = "";
|
|
417
|
+
}
|
|
418
|
+
// implements REQ-009
|
|
419
|
+
isProcessUsable() {
|
|
420
|
+
return Boolean(this.process?.stdin &&
|
|
421
|
+
!this.process?.killed &&
|
|
422
|
+
this.process?.exitCode === null);
|
|
423
|
+
}
|
|
413
424
|
extractBindings(output) {
|
|
414
425
|
const bindings = {};
|
|
415
426
|
const lines = output.split("\n");
|
|
@@ -447,30 +458,44 @@ export class PrologProcess {
|
|
|
447
458
|
return simpleError || "Unknown error";
|
|
448
459
|
}
|
|
449
460
|
isRunning() {
|
|
450
|
-
return this.process
|
|
461
|
+
return Boolean(this.process && !this.process.killed && this.process?.exitCode === null);
|
|
451
462
|
}
|
|
452
463
|
getPid() {
|
|
453
464
|
return this.process?.pid || 0;
|
|
454
465
|
}
|
|
455
466
|
async terminate() {
|
|
467
|
+
if (this.terminationPromise) {
|
|
468
|
+
await this.terminationPromise;
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
456
471
|
if (this.onProcessExit) {
|
|
457
472
|
process.off("exit", this.onProcessExit);
|
|
458
473
|
this.onProcessExit = null;
|
|
459
474
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
475
|
+
const current = this.process;
|
|
476
|
+
this.process = null;
|
|
477
|
+
this.clearQueryBuffers();
|
|
478
|
+
if (current) {
|
|
479
|
+
this.terminationPromise = (async () => {
|
|
480
|
+
current.stdin?.end();
|
|
481
|
+
current.kill("SIGTERM");
|
|
482
|
+
await new Promise((resolve) => {
|
|
483
|
+
const timeout = setTimeout(() => {
|
|
484
|
+
current.kill("SIGKILL");
|
|
485
|
+
resolve(undefined);
|
|
486
|
+
}, 1000);
|
|
487
|
+
current.on("exit", () => {
|
|
488
|
+
clearTimeout(timeout);
|
|
489
|
+
resolve(undefined);
|
|
490
|
+
});
|
|
471
491
|
});
|
|
472
|
-
});
|
|
473
|
-
|
|
492
|
+
})();
|
|
493
|
+
try {
|
|
494
|
+
await this.terminationPromise;
|
|
495
|
+
}
|
|
496
|
+
finally {
|
|
497
|
+
this.terminationPromise = null;
|
|
498
|
+
}
|
|
474
499
|
}
|
|
475
500
|
}
|
|
476
501
|
}
|
|
@@ -24,6 +24,10 @@ Consult this skill before any Kibi knowledge base operation, on first interactio
|
|
|
24
24
|
|
|
25
25
|
Interact with the knowledge base exclusively through MCP tools. Do not read or edit files inside `.kb/` directly. Do not run any `kibi` CLI commands from the agent session. The MCP surface is the only sanctioned interface for agents.
|
|
26
26
|
|
|
27
|
+
### Tool Name Prefixes
|
|
28
|
+
|
|
29
|
+
Kibi's canonical MCP names are `kb_search`, `kb_query`, `kb_upsert`, `kb_check`, and related `kb_*` tools. Some hosts add a server prefix when exposing tools to agents. In OpenCode, use the visible `kibi_kb_search`, `kibi_kb_query`, `kibi_kb_upsert`, and `kibi_kb_check` names when exact tool identifiers are required; they map to the same canonical MCP names.
|
|
30
|
+
|
|
27
31
|
## Discovery-First Workflow
|
|
28
32
|
|
|
29
33
|
Always discover before you mutate. Start with `kb_search` for exploratory discovery across metadata and markdown body text. Split broad queries into 1-3 focused probes. Review top hits for relevance before concluding the KB lacks knowledge.
|
|
@@ -6,7 +6,7 @@ type TraceabilityRelationship = {
|
|
|
6
6
|
export interface ExtractedSymbol {
|
|
7
7
|
id: string;
|
|
8
8
|
name: string;
|
|
9
|
-
kind: "function" | "class" | "interface" | "type" | "variable" | "enum" | "unknown";
|
|
9
|
+
kind: "function" | "class" | "method" | "interface" | "type" | "variable" | "enum" | "unknown";
|
|
10
10
|
location: {
|
|
11
11
|
file: string;
|
|
12
12
|
startLine: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbol-extract.d.ts","sourceRoot":"","sources":["../../src/traceability/symbol-extract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7D,KAAK,wBAAwB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAU7D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EACA,UAAU,GACV,OAAO,GACP,WAAW,GACX,MAAM,GACN,UAAU,GACV,MAAM,GACN,SAAS,CAAC;IACd,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC5C;AAED,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAE9D,wBAAgB,+BAA+B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAG5E;AAkOD,wBAAgB,4BAA4B,CAE1C,UAAU,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,cAAc,GAC9B,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"symbol-extract.d.ts","sourceRoot":"","sources":["../../src/traceability/symbol-extract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7D,KAAK,wBAAwB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAU7D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EACA,UAAU,GACV,OAAO,GACP,QAAQ,GACR,WAAW,GACX,MAAM,GACN,UAAU,GACV,MAAM,GACN,SAAS,CAAC;IACd,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC5C;AAED,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAE9D,wBAAgB,+BAA+B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAG5E;AAkOD,wBAAgB,4BAA4B,CAE1C,UAAU,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,cAAc,GAC9B,eAAe,EAAE,CAyOnB"}
|
|
@@ -229,15 +229,30 @@ stagedFile, manifestLookup) {
|
|
|
229
229
|
const start = cls.getNameNode()?.getStart() ?? cls.getStart();
|
|
230
230
|
const end = cls.getEnd();
|
|
231
231
|
const span = getSpan(start, end);
|
|
232
|
-
const reqLinks = parseReqDirectives(
|
|
233
|
-
.getJsDocs()
|
|
234
|
-
.map((d) => d.getFullText())
|
|
235
|
-
.join("\n")}`);
|
|
232
|
+
const reqLinks = parseReqDirectives(getJsDocText(cls.getJsDocs()));
|
|
236
233
|
results.push(buildSymbolResult(stagedFile, name, "class", span, reqLinks, manifestLookup));
|
|
237
234
|
}
|
|
238
235
|
catch {
|
|
239
236
|
void stagedFile.path;
|
|
240
237
|
}
|
|
238
|
+
for (const method of typeof cls.getMethods === "function"
|
|
239
|
+
? cls.getMethods()
|
|
240
|
+
: []) {
|
|
241
|
+
try {
|
|
242
|
+
const name = formatMethodSymbolName(cls.getName(), method.getName());
|
|
243
|
+
const start = method.getNameNode()?.getStart() ?? method.getStart();
|
|
244
|
+
const end = method.getEnd();
|
|
245
|
+
const span = getSpan(start, end);
|
|
246
|
+
const reqLinks = parseReqDirectives(`${method.getFullText()}\n${method
|
|
247
|
+
.getJsDocs()
|
|
248
|
+
.map((d) => d.getFullText())
|
|
249
|
+
.join("\n")}`);
|
|
250
|
+
results.push(buildSymbolResult(stagedFile, name, "method", span, reqLinks, manifestLookup));
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
void stagedFile.path;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
241
256
|
}
|
|
242
257
|
// Enums
|
|
243
258
|
for (const en of sf.getEnums()) {
|
|
@@ -255,7 +270,9 @@ stagedFile, manifestLookup) {
|
|
|
255
270
|
void stagedFile.path;
|
|
256
271
|
}
|
|
257
272
|
}
|
|
258
|
-
for (const iface of typeof sf.getInterfaces === "function"
|
|
273
|
+
for (const iface of typeof sf.getInterfaces === "function"
|
|
274
|
+
? sf.getInterfaces()
|
|
275
|
+
: []) {
|
|
259
276
|
if (!iface.isExported())
|
|
260
277
|
continue;
|
|
261
278
|
try {
|
|
@@ -270,7 +287,9 @@ stagedFile, manifestLookup) {
|
|
|
270
287
|
void stagedFile.path;
|
|
271
288
|
}
|
|
272
289
|
}
|
|
273
|
-
for (const alias of typeof sf.getTypeAliases === "function"
|
|
290
|
+
for (const alias of typeof sf.getTypeAliases === "function"
|
|
291
|
+
? sf.getTypeAliases()
|
|
292
|
+
: []) {
|
|
274
293
|
if (!alias.isExported())
|
|
275
294
|
continue;
|
|
276
295
|
try {
|
|
@@ -311,6 +330,12 @@ stagedFile, manifestLookup) {
|
|
|
311
330
|
}
|
|
312
331
|
return results;
|
|
313
332
|
}
|
|
333
|
+
function formatMethodSymbolName(className, methodName) {
|
|
334
|
+
return className ? `${className}.${methodName}` : methodName;
|
|
335
|
+
}
|
|
336
|
+
function getJsDocText(jsDocs) {
|
|
337
|
+
return jsDocs.map((d) => d.getFullText()).join("\n");
|
|
338
|
+
}
|
|
314
339
|
function intersectingHunks(startLine, endLine, hunks) {
|
|
315
340
|
const out = [];
|
|
316
341
|
for (const h of hunks) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kibi-cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Kibi CLI for knowledge base management",
|
|
6
6
|
"engines": {
|
|
@@ -11,13 +11,7 @@
|
|
|
11
11
|
"bin": {
|
|
12
12
|
"kibi": "bin/kibi"
|
|
13
13
|
},
|
|
14
|
-
"files": [
|
|
15
|
-
"dist",
|
|
16
|
-
"bin",
|
|
17
|
-
"schema",
|
|
18
|
-
"src/schemas",
|
|
19
|
-
"src/public"
|
|
20
|
-
],
|
|
14
|
+
"files": ["dist", "bin", "schema", "src/schemas", "src/public"],
|
|
21
15
|
"scripts": {
|
|
22
16
|
"build": "tsc -p tsconfig.json && mkdir -p dist/public/skills && cp -r src/public/skills/. dist/public/skills/",
|
|
23
17
|
"prepack": "npm run build"
|
|
@@ -24,6 +24,10 @@ Consult this skill before any Kibi knowledge base operation, on first interactio
|
|
|
24
24
|
|
|
25
25
|
Interact with the knowledge base exclusively through MCP tools. Do not read or edit files inside `.kb/` directly. Do not run any `kibi` CLI commands from the agent session. The MCP surface is the only sanctioned interface for agents.
|
|
26
26
|
|
|
27
|
+
### Tool Name Prefixes
|
|
28
|
+
|
|
29
|
+
Kibi's canonical MCP names are `kb_search`, `kb_query`, `kb_upsert`, `kb_check`, and related `kb_*` tools. Some hosts add a server prefix when exposing tools to agents. In OpenCode, use the visible `kibi_kb_search`, `kibi_kb_query`, `kibi_kb_upsert`, and `kibi_kb_check` names when exact tool identifiers are required; they map to the same canonical MCP names.
|
|
30
|
+
|
|
27
31
|
## Discovery-First Workflow
|
|
28
32
|
|
|
29
33
|
Always discover before you mutate. Start with `kb_search` for exploratory discovery across metadata and markdown body text. Split broad queries into 1-3 focused probes. Review top hits for relevance before concluding the KB lacks knowledge.
|