project-librarian 0.5.5 → 0.5.7
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/CONTRIBUTING.md +36 -0
- package/README.ko.md +58 -365
- package/README.md +56 -363
- package/SKILL.md +7 -0
- package/dist/args.js +9 -1
- package/dist/code-index/extractors/light-languages.js +285 -0
- package/dist/code-index/extractors/registry.js +12 -0
- package/dist/code-index/extractors/shared.js +18 -1
- package/dist/code-index/extractors/typescript.js +30 -16
- package/dist/code-index/index-health.js +4 -3
- package/dist/code-index/modes.js +193 -33
- package/dist/code-index/native-helper-matrix.js +99 -0
- package/dist/code-index/native-helper.js +292 -0
- package/dist/code-index/schema.js +72 -13
- package/dist/code-index/search.js +1 -1
- package/dist/code-index-file-policy.js +9 -1
- package/dist/code-index.js +363 -12
- package/dist/init-project-wiki.js +14 -0
- package/dist/install-skill.js +22 -2
- package/dist/native/darwin-arm64/project-librarian-indexer +0 -0
- package/dist/native/darwin-x64/project-librarian-indexer +0 -0
- package/dist/native/linux-arm64/project-librarian-indexer +0 -0
- package/dist/native/linux-arm64-musl/project-librarian-indexer +0 -0
- package/dist/native/linux-x64/project-librarian-indexer +0 -0
- package/dist/native/linux-x64-musl/project-librarian-indexer +0 -0
- package/dist/native/project-librarian-indexer-manifest.json +70 -0
- package/dist/native/win32-arm64/project-librarian-indexer.exe +0 -0
- package/dist/native/win32-x64/project-librarian-indexer.exe +0 -0
- package/docs/README.md +11 -0
- package/docs/benchmarks.md +64 -0
- package/docs/cli-reference.md +61 -0
- package/docs/code-evidence.md +93 -0
- package/docs/ko/README.md +13 -0
- package/docs/ko/benchmarks.md +64 -0
- package/docs/ko/cli-reference.md +61 -0
- package/docs/ko/code-evidence.md +93 -0
- package/docs/ko/maintainer.md +76 -0
- package/docs/ko/usage.md +168 -0
- package/docs/maintainer.md +76 -0
- package/docs/usage.md +176 -0
- package/package.json +11 -1
package/dist/code-index.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.CodeEvidenceIndexUnavailableError = exports.codeContextPackTruncationNotice = exports.codeContextPackCharCap = exports.codeIndexSnapshot = exports.workspaceSummary = exports.workspaceDependencyGraph = exports.searchSymbols = exports.ownershipInfo = exports.ownershipContext = exports.matchedCodeownerRules = exports.evidenceCoverage = exports.codeownerRules = void 0;
|
|
36
|
+
exports.CodeEvidenceIndexUnavailableError = exports.nativeCodeIndexAutoFileThreshold = exports.codeContextPackTruncationNotice = exports.codeContextPackCharCap = exports.codeIndexSnapshot = exports.workspaceSummary = exports.workspaceDependencyGraph = exports.searchSymbols = exports.ownershipInfo = exports.ownershipContext = exports.matchedCodeownerRules = exports.evidenceCoverage = exports.codeownerRules = void 0;
|
|
37
37
|
exports.codeIndexStaleness = codeIndexStaleness;
|
|
38
38
|
exports.codeIndexHealth = codeIndexHealth;
|
|
39
39
|
exports.codeImpact = codeImpact;
|
|
@@ -61,6 +61,7 @@ const registry_1 = require("./code-index/extractors/registry");
|
|
|
61
61
|
const shared_1 = require("./code-index/extractors/shared");
|
|
62
62
|
const index_health_1 = require("./code-index/index-health");
|
|
63
63
|
const modes_1 = require("./code-index/modes");
|
|
64
|
+
const native_helper_1 = require("./code-index/native-helper");
|
|
64
65
|
const ownership_1 = require("./code-index/ownership");
|
|
65
66
|
Object.defineProperty(exports, "codeownerRules", { enumerable: true, get: function () { return ownership_1.codeownerRules; } });
|
|
66
67
|
Object.defineProperty(exports, "matchedCodeownerRules", { enumerable: true, get: function () { return ownership_1.matchedCodeownerRules; } });
|
|
@@ -77,6 +78,8 @@ Object.defineProperty(exports, "searchSymbols", { enumerable: true, get: functio
|
|
|
77
78
|
const workspace_1 = require("./workspace");
|
|
78
79
|
exports.codeContextPackCharCap = 4000;
|
|
79
80
|
exports.codeContextPackTruncationNotice = "[truncated - refine the query]";
|
|
81
|
+
exports.nativeCodeIndexAutoFileThreshold = 1;
|
|
82
|
+
const codeFileFingerprintPaths = new Map();
|
|
80
83
|
function fail(message) {
|
|
81
84
|
console.error(message);
|
|
82
85
|
process.exit(1);
|
|
@@ -110,31 +113,82 @@ function selectedCodeParserMode() {
|
|
|
110
113
|
return "tree-sitter";
|
|
111
114
|
fail(`invalid --code-parser: ${args_1.codeParser}; expected one of: default, tree-sitter`);
|
|
112
115
|
}
|
|
116
|
+
function selectedCodeIndexEngine() {
|
|
117
|
+
const requested = args_1.codeIndexEngine.trim().toLowerCase();
|
|
118
|
+
if (!requested || requested === "auto")
|
|
119
|
+
return "auto";
|
|
120
|
+
if (requested === "typescript")
|
|
121
|
+
return "typescript";
|
|
122
|
+
if (requested === "native-rust")
|
|
123
|
+
return "native-rust";
|
|
124
|
+
fail(`invalid --code-index-engine: ${args_1.codeIndexEngine}; expected one of: auto, typescript, native-rust`);
|
|
125
|
+
}
|
|
126
|
+
function codeIndexEngineSelectionContext(discoveredFiles, parserMode) {
|
|
127
|
+
let nativeEligibleFileCount = 0;
|
|
128
|
+
for (const filePath of discoveredFiles) {
|
|
129
|
+
const language = (0, code_index_file_policy_1.fileLanguage)(filePath) || "config";
|
|
130
|
+
if (nativeAutoEligibleProfile((0, registry_1.extractionProfile)(filePath, language, parserMode)))
|
|
131
|
+
nativeEligibleFileCount += 1;
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
discoveredFileCount: discoveredFiles.length,
|
|
135
|
+
nativeEligibleFileCount,
|
|
136
|
+
nativeIneligibleFileCount: discoveredFiles.length - nativeEligibleFileCount,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function shouldUseNativeCodeIndexAuto(context) {
|
|
140
|
+
return context.nativeEligibleFileCount >= exports.nativeCodeIndexAutoFileThreshold
|
|
141
|
+
&& (0, native_helper_1.nativeCodeIndexHelperAvailable)();
|
|
142
|
+
}
|
|
143
|
+
function nativeCodeIndexAvailable() {
|
|
144
|
+
return (0, native_helper_1.nativeCodeIndexHelperAvailable)();
|
|
145
|
+
}
|
|
113
146
|
function normalizedMtimeMs(stat) {
|
|
114
147
|
return Number(stat.mtimeMs.toFixed(3));
|
|
115
148
|
}
|
|
116
149
|
function readCodeFileFingerprint(relativePath) {
|
|
117
|
-
const
|
|
150
|
+
const discovered = (0, code_index_file_policy_1.cachedDiscoveredCodeFileStat)(relativePath);
|
|
151
|
+
const { absolutePath, stat } = discovered ?? (0, workspace_1.requireContainedProjectFile)(relativePath, "code-index file");
|
|
152
|
+
codeFileFingerprintPaths.set(relativePath, absolutePath);
|
|
118
153
|
return {
|
|
119
154
|
mtimeMs: normalizedMtimeMs(stat),
|
|
120
155
|
path: relativePath,
|
|
121
156
|
size: stat.size,
|
|
122
157
|
};
|
|
123
158
|
}
|
|
124
|
-
function
|
|
125
|
-
|
|
159
|
+
function lineCount(text) {
|
|
160
|
+
if (text.length === 0)
|
|
161
|
+
return 0;
|
|
162
|
+
let lines = 1;
|
|
163
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
164
|
+
if (text.charCodeAt(index) === 10)
|
|
165
|
+
lines += 1;
|
|
166
|
+
}
|
|
167
|
+
return lines;
|
|
168
|
+
}
|
|
169
|
+
function readCodeFile(relativePath, parserMode = "default", fingerprint) {
|
|
170
|
+
let effectiveFingerprint = fingerprint;
|
|
171
|
+
let absolutePath = effectiveFingerprint ? codeFileFingerprintPaths.get(relativePath) : undefined;
|
|
172
|
+
if (!absolutePath || !effectiveFingerprint) {
|
|
173
|
+
const contained = (0, workspace_1.requireContainedProjectFile)(relativePath, "code-index file");
|
|
174
|
+
absolutePath = contained.absolutePath;
|
|
175
|
+
effectiveFingerprint ??= {
|
|
176
|
+
mtimeMs: normalizedMtimeMs(contained.stat),
|
|
177
|
+
path: relativePath,
|
|
178
|
+
size: contained.stat.size,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
126
181
|
const text = fs.readFileSync(absolutePath, "utf8");
|
|
127
|
-
const fingerprint = readCodeFileFingerprint(relativePath);
|
|
128
182
|
const language = (0, code_index_file_policy_1.fileLanguage)(relativePath) || "config";
|
|
129
183
|
return {
|
|
130
|
-
bytes:
|
|
184
|
+
bytes: effectiveFingerprint.size,
|
|
131
185
|
hash: crypto.createHash("sha256").update(text).digest("hex"),
|
|
132
186
|
language,
|
|
133
|
-
lines: text
|
|
134
|
-
mtimeMs:
|
|
187
|
+
lines: lineCount(text),
|
|
188
|
+
mtimeMs: effectiveFingerprint.mtimeMs,
|
|
135
189
|
path: relativePath,
|
|
136
190
|
profile: (0, registry_1.extractionProfile)(relativePath, language, parserMode),
|
|
137
|
-
size:
|
|
191
|
+
size: effectiveFingerprint.size,
|
|
138
192
|
text,
|
|
139
193
|
};
|
|
140
194
|
}
|
|
@@ -143,8 +197,9 @@ function extractionBackendForProfile(profile) {
|
|
|
143
197
|
return extractionBackendRegistry.backendForProfile(profile);
|
|
144
198
|
}
|
|
145
199
|
function indexCodeFile(file, statements) {
|
|
146
|
-
|
|
147
|
-
statements.
|
|
200
|
+
const ftsRowid = (0, schema_1.fileFtsRowid)(file.path);
|
|
201
|
+
statements.insertFile.run(file.path, ftsRowid, file.language, file.profile, file.language === "config" ? "config" : "source", file.bytes, file.lines, file.hash, file.mtimeMs, file.size);
|
|
202
|
+
statements.insertFileFts.run(ftsRowid, file.path, file.language, file.profile, file.text);
|
|
148
203
|
extractionBackendForProfile(file.profile).index(file, statements);
|
|
149
204
|
}
|
|
150
205
|
function printRows(rows) {
|
|
@@ -173,6 +228,295 @@ function removeDatabaseFiles(databasePath) {
|
|
|
173
228
|
fs.unlinkSync(filePath);
|
|
174
229
|
}
|
|
175
230
|
}
|
|
231
|
+
function moveDatabaseFiles(sourcePath, targetPath) {
|
|
232
|
+
const backupPath = `${targetPath}.backup-${process.pid}-${Date.now()}`;
|
|
233
|
+
removeDatabaseFiles(backupPath);
|
|
234
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
235
|
+
const target = `${targetPath}${suffix}`;
|
|
236
|
+
if (fs.existsSync(target))
|
|
237
|
+
fs.renameSync(target, `${backupPath}${suffix}`);
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
241
|
+
const source = `${sourcePath}${suffix}`;
|
|
242
|
+
if (fs.existsSync(source))
|
|
243
|
+
fs.renameSync(source, `${targetPath}${suffix}`);
|
|
244
|
+
}
|
|
245
|
+
removeDatabaseFiles(backupPath);
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
removeDatabaseFiles(targetPath);
|
|
249
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
250
|
+
const backup = `${backupPath}${suffix}`;
|
|
251
|
+
if (fs.existsSync(backup))
|
|
252
|
+
fs.renameSync(backup, `${targetPath}${suffix}`);
|
|
253
|
+
}
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function removeTemporaryDatabaseFiles(databasePath) {
|
|
258
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
259
|
+
const filePath = `${databasePath}${suffix}`;
|
|
260
|
+
if (fs.existsSync(filePath))
|
|
261
|
+
fs.unlinkSync(filePath);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function nativeCodeIndexFileFor(filePath, parserMode) {
|
|
265
|
+
const fingerprint = readCodeFileFingerprint(filePath);
|
|
266
|
+
const language = (0, code_index_file_policy_1.fileLanguage)(filePath) || "config";
|
|
267
|
+
return {
|
|
268
|
+
...fingerprint,
|
|
269
|
+
language,
|
|
270
|
+
profile: (0, registry_1.extractionProfile)(filePath, language, parserMode),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function nativeCodeIndexFileFromCodeFile(file) {
|
|
274
|
+
return {
|
|
275
|
+
language: file.language,
|
|
276
|
+
mtimeMs: file.mtimeMs,
|
|
277
|
+
path: file.path,
|
|
278
|
+
profile: file.profile,
|
|
279
|
+
size: file.size,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function nativeCodeIndexFileFromFingerprint(file, parserMode) {
|
|
283
|
+
const language = (0, code_index_file_policy_1.fileLanguage)(file.path) || "config";
|
|
284
|
+
return {
|
|
285
|
+
language,
|
|
286
|
+
mtimeMs: file.mtimeMs,
|
|
287
|
+
path: file.path,
|
|
288
|
+
profile: (0, registry_1.extractionProfile)(file.path, language, parserMode),
|
|
289
|
+
size: file.size,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
function nativeEligibleProfile(profile) {
|
|
293
|
+
return nativeAutoEligibleProfile(profile) || profile === "config" || profile === "inventory-only";
|
|
294
|
+
}
|
|
295
|
+
function nativeCodeIndexIncrementalEligible(files, parserMode) {
|
|
296
|
+
return files.every((file) => nativeEligibleProfile(nativeCodeIndexFileFromFingerprint(file, parserMode).profile));
|
|
297
|
+
}
|
|
298
|
+
function nativeAutoEligibleProfile(profile) {
|
|
299
|
+
return [
|
|
300
|
+
"typescript-ast",
|
|
301
|
+
"python-light",
|
|
302
|
+
"go-light",
|
|
303
|
+
"c-light",
|
|
304
|
+
"cpp-light",
|
|
305
|
+
"csharp-light",
|
|
306
|
+
"java-light",
|
|
307
|
+
"kotlin-light",
|
|
308
|
+
"php-light",
|
|
309
|
+
"rust-light",
|
|
310
|
+
"swift-light",
|
|
311
|
+
].includes(profile);
|
|
312
|
+
}
|
|
313
|
+
function nativeCodeIndexOutputMode() {
|
|
314
|
+
const requested = (process.env.PROJECT_LIBRARIAN_NATIVE_INDEXER_STRATEGY ?? "sqlite-direct").trim();
|
|
315
|
+
if (requested === "row-stream" || requested === "sqlite-bridge" || requested === "sqlite-direct")
|
|
316
|
+
return requested;
|
|
317
|
+
fail(`invalid PROJECT_LIBRARIAN_NATIVE_INDEXER_STRATEGY: ${requested}; expected row-stream, sqlite-bridge, or sqlite-direct`);
|
|
318
|
+
}
|
|
319
|
+
function appendTypeScriptPartitionToNativeDatabase(databasePath, files, parserMode) {
|
|
320
|
+
if (files.length === 0)
|
|
321
|
+
return 0;
|
|
322
|
+
const database = openDatabase(databasePath);
|
|
323
|
+
try {
|
|
324
|
+
const statements = (0, schema_1.createIndexStatements)(database);
|
|
325
|
+
database.exec("BEGIN");
|
|
326
|
+
for (const file of files)
|
|
327
|
+
indexCodeFile(readCodeFile(file.path, parserMode, file), statements);
|
|
328
|
+
database.exec("COMMIT");
|
|
329
|
+
return files.length;
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
try {
|
|
333
|
+
database.exec("ROLLBACK");
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
// Ignore rollback failures after helper-created database errors.
|
|
337
|
+
}
|
|
338
|
+
throw error;
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
database.close();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
function writeNativeRowsToDatabase(databasePath, rows, scopes, parserMode) {
|
|
345
|
+
removeDatabaseFiles(databasePath);
|
|
346
|
+
const database = openDatabase(databasePath);
|
|
347
|
+
try {
|
|
348
|
+
(0, schema_1.setupDatabase)(database, { secondaryIndexes: false });
|
|
349
|
+
const statements = (0, schema_1.createIndexStatements)(database);
|
|
350
|
+
database.exec("BEGIN");
|
|
351
|
+
statements.insertMeta.run("created_at", new Date().toISOString());
|
|
352
|
+
(0, schema_1.writeIndexMetadata)(scopes, parserMode, statements);
|
|
353
|
+
for (const file of rows.files) {
|
|
354
|
+
const ftsRowid = (0, schema_1.fileFtsRowid)(file.path);
|
|
355
|
+
statements.insertFile.run(file.path, ftsRowid, file.language, file.profile, file.kind, file.bytes, file.lines, file.hash, file.mtime_ms, file.size);
|
|
356
|
+
statements.insertFileFts.run(ftsRowid, file.path, file.language, file.profile, file.content);
|
|
357
|
+
}
|
|
358
|
+
for (const symbol of rows.symbols) {
|
|
359
|
+
statements.insertSymbol.run(symbol.name, symbol.kind, symbol.file_path, symbol.line, symbol.signature);
|
|
360
|
+
statements.insertSymbolFts.run(symbol.name, symbol.kind, symbol.file_path, symbol.signature);
|
|
361
|
+
}
|
|
362
|
+
for (const imported of rows.imports) {
|
|
363
|
+
statements.insertImport.run(imported.from_file, imported.to_ref, imported.imported, imported.line, imported.raw);
|
|
364
|
+
}
|
|
365
|
+
for (const route of rows.routes) {
|
|
366
|
+
statements.insertRoute.run(route.method, route.route, route.file_path, route.line, route.handler);
|
|
367
|
+
}
|
|
368
|
+
for (const config of rows.configs) {
|
|
369
|
+
statements.insertConfig.run(config.key, config.value, config.file_path, config.line);
|
|
370
|
+
}
|
|
371
|
+
for (const edge of rows.edges) {
|
|
372
|
+
statements.insertEdge.run(edge.kind, edge.source_kind, edge.source, edge.target_kind, edge.target, edge.file_path, edge.line, edge.evidence);
|
|
373
|
+
}
|
|
374
|
+
(0, schema_1.createSecondaryIndexes)(database);
|
|
375
|
+
database.exec("COMMIT");
|
|
376
|
+
}
|
|
377
|
+
catch (error) {
|
|
378
|
+
try {
|
|
379
|
+
database.exec("ROLLBACK");
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
// Ignore rollback failures after row-stream setup errors.
|
|
383
|
+
}
|
|
384
|
+
throw error;
|
|
385
|
+
}
|
|
386
|
+
finally {
|
|
387
|
+
database.close();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function runNativeCodeIndexMode(request) {
|
|
391
|
+
let helperPath = "";
|
|
392
|
+
try {
|
|
393
|
+
helperPath = (0, native_helper_1.requireNativeCodeIndexHelperPath)();
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
397
|
+
}
|
|
398
|
+
prepareOutputPath();
|
|
399
|
+
const tempDatabasePath = `${request.databasePath.absolutePath}.native-${process.pid}-${Date.now()}.tmp`;
|
|
400
|
+
removeDatabaseFiles(tempDatabasePath);
|
|
401
|
+
const manifestFiles = [];
|
|
402
|
+
const nativeFiles = [];
|
|
403
|
+
const typescriptFiles = [];
|
|
404
|
+
for (const filePath of request.discoveredFiles) {
|
|
405
|
+
const file = nativeCodeIndexFileFor(filePath, request.parserMode);
|
|
406
|
+
manifestFiles.push(file);
|
|
407
|
+
if (nativeEligibleProfile(file.profile))
|
|
408
|
+
nativeFiles.push(file);
|
|
409
|
+
else
|
|
410
|
+
typescriptFiles.push(file);
|
|
411
|
+
}
|
|
412
|
+
const typescriptProfiles = [...new Set(typescriptFiles.map((file) => file.profile))].sort();
|
|
413
|
+
const outputMode = nativeCodeIndexOutputMode();
|
|
414
|
+
const rowsPath = `${tempDatabasePath}.rows.json`;
|
|
415
|
+
const job = (0, native_helper_1.buildNativeCodeIndexJob)({
|
|
416
|
+
database_path: tempDatabasePath,
|
|
417
|
+
files: nativeFiles,
|
|
418
|
+
output_mode: outputMode,
|
|
419
|
+
parser_mode: request.parserMode,
|
|
420
|
+
schema_version: schema_1.codeIndexSchemaVersion,
|
|
421
|
+
scopes: request.scopes,
|
|
422
|
+
...(outputMode === "row-stream" ? { rows_path: rowsPath } : {}),
|
|
423
|
+
});
|
|
424
|
+
let summary;
|
|
425
|
+
let typescriptIndexedFiles = 0;
|
|
426
|
+
try {
|
|
427
|
+
if (outputMode === "row-stream") {
|
|
428
|
+
const result = (0, native_helper_1.runNativeCodeIndexRowsHelper)(job, { helperPath });
|
|
429
|
+
summary = result.summary;
|
|
430
|
+
writeNativeRowsToDatabase(tempDatabasePath, result.rows, request.scopes, request.parserMode);
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
summary = (0, native_helper_1.runNativeCodeIndexHelper)(job, { helperPath });
|
|
434
|
+
}
|
|
435
|
+
if (!fs.existsSync(tempDatabasePath)) {
|
|
436
|
+
fail(`native code index helper did not create database: ${tempDatabasePath}`);
|
|
437
|
+
}
|
|
438
|
+
typescriptIndexedFiles = appendTypeScriptPartitionToNativeDatabase(tempDatabasePath, typescriptFiles, request.parserMode);
|
|
439
|
+
moveDatabaseFiles(tempDatabasePath, request.databasePath.absolutePath);
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
removeTemporaryDatabaseFiles(tempDatabasePath);
|
|
443
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
444
|
+
}
|
|
445
|
+
finally {
|
|
446
|
+
if (fs.existsSync(rowsPath))
|
|
447
|
+
fs.unlinkSync(rowsPath);
|
|
448
|
+
}
|
|
449
|
+
console.log("Project wiki code evidence index complete.");
|
|
450
|
+
console.log(`database: ${request.databasePath.relativePath}`);
|
|
451
|
+
console.log("mode: full");
|
|
452
|
+
console.log(`parser_mode: ${request.parserMode}`);
|
|
453
|
+
console.log(`engine: ${typescriptIndexedFiles > 0 ? "mixed-native-rust" : "native-rust"}`);
|
|
454
|
+
if (request.requestedEngine === "auto")
|
|
455
|
+
console.log("engine_selection: auto");
|
|
456
|
+
console.log(`native_strategy: ${outputMode}`);
|
|
457
|
+
console.log(`scopes: ${request.scopes.join(", ")}`);
|
|
458
|
+
console.log(`files: ${manifestFiles.length}`);
|
|
459
|
+
console.log(`native_files: ${nativeFiles.length}`);
|
|
460
|
+
console.log(`typescript_files: ${typescriptIndexedFiles}`);
|
|
461
|
+
if (typescriptProfiles.length > 0)
|
|
462
|
+
console.log(`typescript_profiles: ${typescriptProfiles.join(", ")}`);
|
|
463
|
+
console.log(`reindexed_files: ${manifestFiles.length}`);
|
|
464
|
+
console.log(`deleted_files: ${summary.deleted_files ?? 0}`);
|
|
465
|
+
console.log(`unchanged_files: ${summary.unchanged_files ?? 0}`);
|
|
466
|
+
}
|
|
467
|
+
function runNativeCodeIndexIncrementalMode(request) {
|
|
468
|
+
let helperPath = "";
|
|
469
|
+
try {
|
|
470
|
+
helperPath = (0, native_helper_1.requireNativeCodeIndexHelperPath)();
|
|
471
|
+
}
|
|
472
|
+
catch (error) {
|
|
473
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
474
|
+
}
|
|
475
|
+
const nativeFiles = request.reindexedFiles.map((file) => nativeCodeIndexFileFromFingerprint(file, request.parserMode));
|
|
476
|
+
const ineligibleProfiles = [...new Set(nativeFiles
|
|
477
|
+
.filter((file) => !nativeEligibleProfile(file.profile))
|
|
478
|
+
.map((file) => file.profile))].sort();
|
|
479
|
+
if (ineligibleProfiles.length > 0) {
|
|
480
|
+
fail(`native incremental writer does not support parser profiles: ${ineligibleProfiles.join(", ")}`);
|
|
481
|
+
}
|
|
482
|
+
prepareOutputPath();
|
|
483
|
+
const outputMode = "sqlite-direct";
|
|
484
|
+
const job = (0, native_helper_1.buildNativeCodeIndexJob)({
|
|
485
|
+
database_path: request.databasePath.absolutePath,
|
|
486
|
+
deleted_paths: request.deletedPaths,
|
|
487
|
+
files: nativeFiles,
|
|
488
|
+
mode: "incremental",
|
|
489
|
+
output_mode: outputMode,
|
|
490
|
+
parser_mode: request.parserMode,
|
|
491
|
+
schema_version: schema_1.codeIndexSchemaVersion,
|
|
492
|
+
scopes: request.scopes,
|
|
493
|
+
});
|
|
494
|
+
let summary;
|
|
495
|
+
try {
|
|
496
|
+
summary = (0, native_helper_1.runNativeCodeIndexHelper)(job, { helperPath });
|
|
497
|
+
if (!fs.existsSync(request.databasePath.absolutePath)) {
|
|
498
|
+
fail(`native incremental writer did not preserve database: ${request.databasePath.absolutePath}`);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
catch (error) {
|
|
502
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
503
|
+
}
|
|
504
|
+
console.log("Project wiki code evidence index complete.");
|
|
505
|
+
console.log(`database: ${request.databasePath.relativePath}`);
|
|
506
|
+
console.log("mode: incremental");
|
|
507
|
+
console.log(`parser_mode: ${request.parserMode}`);
|
|
508
|
+
console.log("engine: native-rust");
|
|
509
|
+
if (request.requestedEngine === "auto")
|
|
510
|
+
console.log("engine_selection: auto");
|
|
511
|
+
console.log(`native_strategy: ${outputMode}`);
|
|
512
|
+
console.log(`scopes: ${request.scopes.join(", ")}`);
|
|
513
|
+
console.log(`files: ${request.discoveredFiles.length}`);
|
|
514
|
+
console.log(`native_files: ${nativeFiles.length}`);
|
|
515
|
+
console.log("typescript_files: 0");
|
|
516
|
+
console.log(`reindexed_files: ${summary.reindexed_files ?? nativeFiles.length}`);
|
|
517
|
+
console.log(`deleted_files: ${summary.deleted_files ?? request.deletedPaths.length}`);
|
|
518
|
+
console.log(`unchanged_files: ${request.unchangedFiles}`);
|
|
519
|
+
}
|
|
176
520
|
function codeIndexStaleness(database) {
|
|
177
521
|
const scopes = (0, schema_1.indexedScopes)(database);
|
|
178
522
|
const parserMode = (0, schema_1.indexedParserMode)(database);
|
|
@@ -194,7 +538,7 @@ function codeIndexStaleness(database) {
|
|
|
194
538
|
}
|
|
195
539
|
if (existing.mtimeMs === file.mtimeMs && existing.size === file.size)
|
|
196
540
|
continue;
|
|
197
|
-
if (readCodeFile(file.path, parserMode).hash !== existing.hash)
|
|
541
|
+
if (readCodeFile(file.path, parserMode, file).hash !== existing.hash)
|
|
198
542
|
changed += 1;
|
|
199
543
|
}
|
|
200
544
|
const deleted = indexedRows.filter((row) => !currentPaths.has(String(row.path))).length;
|
|
@@ -397,13 +741,20 @@ function codeIndexModeRuntime() {
|
|
|
397
741
|
codeScopes,
|
|
398
742
|
fail,
|
|
399
743
|
indexCodeFile,
|
|
744
|
+
nativeCodeIndexAvailable,
|
|
745
|
+
nativeCodeIndexIncrementalEligible,
|
|
400
746
|
openDatabase,
|
|
401
747
|
prepareOutputPath,
|
|
402
748
|
readCodeFileFingerprint,
|
|
403
749
|
readCodeFile,
|
|
404
750
|
removeDatabaseFiles,
|
|
405
751
|
requireExistingIndex,
|
|
752
|
+
runNativeCodeIndexIncrementalMode,
|
|
753
|
+
runNativeCodeIndexMode,
|
|
754
|
+
selectedCodeIndexEngine,
|
|
406
755
|
selectedCodeParserMode,
|
|
756
|
+
codeIndexEngineSelectionContext,
|
|
757
|
+
shouldUseNativeCodeIndexAuto,
|
|
407
758
|
warnIfCodeIndexStale,
|
|
408
759
|
};
|
|
409
760
|
}
|
|
@@ -62,6 +62,8 @@ Options:
|
|
|
62
62
|
--acknowledge-small-repo With --code-index, proceed below the small-repo scale gate after its cost warning.
|
|
63
63
|
--incremental With --code-index, require an existing compatible index and update only changes.
|
|
64
64
|
--code-index-full With --code-index, force a full rebuild even when incremental update is possible.
|
|
65
|
+
--code-index-migrate With --code-index, approve replacing an incompatible schema-version index.
|
|
66
|
+
--code-index-engine <engine> With --code-index, override default auto engine: typescript or native-rust.
|
|
65
67
|
--code-parser <mode> With --code-index, use parser mode default or tree-sitter.
|
|
66
68
|
--code-query <sql> Run conservative read-only SQL over the code evidence index.
|
|
67
69
|
--code-status, --code-files Inspect the code evidence index.
|
|
@@ -165,6 +167,14 @@ if (args_1.codeIndexFullMode && !args_1.codeIndexMode) {
|
|
|
165
167
|
console.error("--code-index-full is only supported with --code-index.");
|
|
166
168
|
process.exit(1);
|
|
167
169
|
}
|
|
170
|
+
if (args_1.codeIndexMigrateMode && !args_1.codeIndexMode) {
|
|
171
|
+
console.error("--code-index-migrate is only supported with --code-index.");
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
if (args_1.codeIndexEngineMode && !args_1.codeIndexMode) {
|
|
175
|
+
console.error("--code-index-engine is only supported with --code-index.");
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
168
178
|
if (args_1.codeParserMode && !args_1.codeIndexMode) {
|
|
169
179
|
console.error("--code-parser is only supported with --code-index.");
|
|
170
180
|
process.exit(1);
|
|
@@ -173,6 +183,10 @@ if (args_1.codeIndexIncrementalMode && args_1.codeIndexFullMode) {
|
|
|
173
183
|
console.error("Use one code index update mode at a time: --incremental or --code-index-full.");
|
|
174
184
|
process.exit(1);
|
|
175
185
|
}
|
|
186
|
+
if (args_1.codeIndexIncrementalMode && args_1.codeIndexMigrateMode) {
|
|
187
|
+
console.error("Use one code index update mode at a time: --incremental or --code-index-migrate.");
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
176
190
|
const activeHandoffModes = [
|
|
177
191
|
args_1.handoffSaveMode ? "--handoff-save" : "",
|
|
178
192
|
args_1.handoffShowMode ? "--handoff-show" : "",
|
package/dist/install-skill.js
CHANGED
|
@@ -52,6 +52,7 @@ const packageFiles = [
|
|
|
52
52
|
"package.json",
|
|
53
53
|
"agents",
|
|
54
54
|
];
|
|
55
|
+
const runtimeDependencyPackages = ["typescript"];
|
|
55
56
|
function fail(message) {
|
|
56
57
|
console.error(message);
|
|
57
58
|
process.exit(1);
|
|
@@ -83,6 +84,18 @@ function installAgents() {
|
|
|
83
84
|
function packageRoot() {
|
|
84
85
|
return path.resolve(__dirname, "..");
|
|
85
86
|
}
|
|
87
|
+
function runtimeDependencySource(packageName) {
|
|
88
|
+
try {
|
|
89
|
+
return path.dirname(require.resolve(`${packageName}/package.json`, { paths: [packageRoot()] }));
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
93
|
+
return fail(`missing runtime dependency ${packageName}: run npm install before installing the Project Librarian skill. Error: ${message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function runtimeDependencyTarget(packageName) {
|
|
97
|
+
return path.join("node_modules", ...packageName.split("/"));
|
|
98
|
+
}
|
|
86
99
|
function userAgentRoot(agent) {
|
|
87
100
|
const home = os.homedir();
|
|
88
101
|
if (agent === "codex")
|
|
@@ -236,11 +249,18 @@ function installedProjectSkillSurfaces() {
|
|
|
236
249
|
}
|
|
237
250
|
function copyPackageFiles(targetRoot, dryRun, labelRoot = targetRoot) {
|
|
238
251
|
const root = packageRoot();
|
|
239
|
-
|
|
252
|
+
const packageRows = packageFiles.map((relativePath) => {
|
|
240
253
|
const source = path.join(root, relativePath);
|
|
241
254
|
const target = path.join(targetRoot, relativePath);
|
|
242
255
|
return [path.join(labelRoot, relativePath), copyPath(source, target, targetRoot, dryRun)];
|
|
243
256
|
});
|
|
257
|
+
const dependencyRows = runtimeDependencyPackages.map((packageName) => {
|
|
258
|
+
const relativePath = runtimeDependencyTarget(packageName);
|
|
259
|
+
const source = runtimeDependencySource(packageName);
|
|
260
|
+
const target = path.join(targetRoot, relativePath);
|
|
261
|
+
return [path.join(labelRoot, relativePath), copyPath(source, target, targetRoot, dryRun)];
|
|
262
|
+
});
|
|
263
|
+
return [...packageRows, ...dependencyRows];
|
|
244
264
|
}
|
|
245
265
|
function syncProjectSkillInstall(agent) {
|
|
246
266
|
return copyPackageFiles(projectSkillTarget(agent), false, projectSkillRelativeRoot(agent)).map(([label, status]) => {
|
|
@@ -261,7 +281,7 @@ function runInstallSkillMode() {
|
|
|
261
281
|
console.log(`Project Librarian skill ${dryRun ? "install dry-run" : "install"} complete.`);
|
|
262
282
|
console.log(`scope: ${scope}`);
|
|
263
283
|
console.log(`agents: ${agents.join(", ")}`);
|
|
264
|
-
console.log("note: install only installs the reusable skill files; it does not create or update AGENTS.md, CLAUDE.md, GEMINI.md, wiki/, .cursor/rules/, .cursor/hooks.json, .gemini/settings.json, .codex/hooks.json, or .claude/settings.json.");
|
|
284
|
+
console.log("note: install only installs the reusable skill files and required local-runner runtime dependencies; it does not create or update AGENTS.md, CLAUDE.md, GEMINI.md, wiki/, .cursor/rules/, .cursor/hooks.json, .gemini/settings.json, .codex/hooks.json, or .claude/settings.json.");
|
|
265
285
|
console.log("compatibility: install-skill remains supported as an alias for install.");
|
|
266
286
|
console.log("next: ask your agent to use Project Librarian from the target project root; the installed skill resolves the local runner.");
|
|
267
287
|
for (const [label, status] of rows) {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"artifact": "project-librarian-indexer",
|
|
3
|
+
"helpers": [
|
|
4
|
+
{
|
|
5
|
+
"architecture": "arm64",
|
|
6
|
+
"format": "mach-o",
|
|
7
|
+
"path": "dist/native/darwin-arm64/project-librarian-indexer",
|
|
8
|
+
"sha256": "f5c69130f6c0441044141c761f1ccdc7e6ee4d06e327ce0f50d43a7aed76cc95",
|
|
9
|
+
"size": 2697520,
|
|
10
|
+
"triple": "darwin-arm64"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"architecture": "x64",
|
|
14
|
+
"format": "mach-o",
|
|
15
|
+
"path": "dist/native/darwin-x64/project-librarian-indexer",
|
|
16
|
+
"sha256": "25041398ba2de3ed749c14103d358ed4a7934a05459eb63c6cf5f6ae58c7fb03",
|
|
17
|
+
"size": 2770592,
|
|
18
|
+
"triple": "darwin-x64"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"architecture": "arm64",
|
|
22
|
+
"format": "elf",
|
|
23
|
+
"path": "dist/native/linux-arm64/project-librarian-indexer",
|
|
24
|
+
"sha256": "01bf4437fd62446958438ac58e9ca8bef811bdc6d70a63fc1a0ca1b627521e67",
|
|
25
|
+
"size": 3065520,
|
|
26
|
+
"triple": "linux-arm64"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"architecture": "arm64",
|
|
30
|
+
"format": "elf",
|
|
31
|
+
"path": "dist/native/linux-arm64-musl/project-librarian-indexer",
|
|
32
|
+
"sha256": "b7287995bea678a6f55bd03761e5b0985d483e875d7594395b81bdb1e90a8dd9",
|
|
33
|
+
"size": 3100840,
|
|
34
|
+
"triple": "linux-arm64-musl"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"architecture": "x64",
|
|
38
|
+
"format": "elf",
|
|
39
|
+
"path": "dist/native/linux-x64/project-librarian-indexer",
|
|
40
|
+
"sha256": "5d93bb7576afbdde0acbde7983a874f2666f0d59227524c1eb42cc75b457c5ed",
|
|
41
|
+
"size": 3110696,
|
|
42
|
+
"triple": "linux-x64"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"architecture": "x64",
|
|
46
|
+
"format": "elf",
|
|
47
|
+
"path": "dist/native/linux-x64-musl/project-librarian-indexer",
|
|
48
|
+
"sha256": "518aea0fc53ed7731751db4bb436a0be98f8583659d51aeff769bedb7a7cb8ab",
|
|
49
|
+
"size": 3247384,
|
|
50
|
+
"triple": "linux-x64-musl"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"architecture": "arm64",
|
|
54
|
+
"format": "pe",
|
|
55
|
+
"path": "dist/native/win32-arm64/project-librarian-indexer.exe",
|
|
56
|
+
"sha256": "e8e5200660a8852d1b7554daf0d16361e29e5599baa5cd406eb3f2266abd98f6",
|
|
57
|
+
"size": 2098688,
|
|
58
|
+
"triple": "win32-arm64"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"architecture": "x64",
|
|
62
|
+
"format": "pe",
|
|
63
|
+
"path": "dist/native/win32-x64/project-librarian-indexer.exe",
|
|
64
|
+
"sha256": "dc076bd61271f23ab87b428c7cbfa3af45911c00f7bf7986a2ed9d517e1cfb6f",
|
|
65
|
+
"size": 2375680,
|
|
66
|
+
"triple": "win32-x64"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"schema_version": 1
|
|
70
|
+
}
|
|
Binary file
|
|
Binary file
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Project Librarian Docs
|
|
2
|
+
|
|
3
|
+
Start from the main [README](../README.md) when evaluating the project. These pages hold the details that are useful after the first-screen overview.
|
|
4
|
+
|
|
5
|
+
| Document | Contents |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| [Usage](usage.md) | Install scopes, runner paths, generated files, migration behavior, and common agent requests. |
|
|
8
|
+
| [Code Evidence](code-evidence.md) | Code-evidence index, MCP server, freshness contract, scale gate, language support, and native helper policy. |
|
|
9
|
+
| [CLI Reference](cli-reference.md) | Complete command and option reference. |
|
|
10
|
+
| [Benchmark Evidence](benchmarks.md) | Published benchmark claims, limits, task-family definitions, and reproduction commands. |
|
|
11
|
+
| [Maintainer Guide](maintainer.md) | Local development, release readiness, trusted publishing, and benchmark operations. |
|