@wrongstack/tools 0.306.4 → 0.307.1
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/audit.js +14 -8
- package/dist/auto-proceed-loop-guard.js +8 -2
- package/dist/bash.js +57 -22
- package/dist/builtin.d.ts +6 -6
- package/dist/builtin.js +11469 -9304
- package/dist/clarify.d.ts +32 -0
- package/dist/codebase-index/ast-invariant-engine.d.ts +102 -0
- package/dist/codebase-index/ast-symbol-mutator.d.ts +28 -0
- package/dist/codebase-index/background-indexer.d.ts +9 -0
- package/dist/codebase-index/codebase-ast-replace-tool.d.ts +31 -0
- package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +42 -0
- package/dist/codebase-index/codebase-invariant-check-tool.d.ts +23 -0
- package/dist/codebase-index/codebase-repo-map-tool.d.ts +22 -0
- package/dist/codebase-index/codebase-skeleton-tool.d.ts +36 -0
- package/dist/codebase-index/codebase-targeted-test-tool.d.ts +30 -0
- package/dist/codebase-index/index.d.ts +11 -1
- package/dist/codebase-index/index.js +4239 -1492
- package/dist/codebase-index/project-server-client-state.d.ts +79 -0
- package/dist/codebase-index/project-server-client.d.ts +3 -71
- package/dist/codebase-index/project-server-protocol.d.ts +1 -0
- package/dist/codebase-index/project-server.js +819 -933
- package/dist/codebase-index/repo-map.d.ts +20 -0
- package/dist/codebase-index/skeleton-extractor.d.ts +64 -0
- package/dist/codebase-index/tree-sitter-parser.d.ts +11 -0
- package/dist/codebase-index/worker.js +790 -914
- package/dist/codebase-index/writer-graph-helpers.d.ts +1 -1
- package/dist/codebase-index/writer-helpers.d.ts +12 -0
- package/dist/codebase-index/writer-mutations.d.ts +26 -0
- package/dist/codebase-index/writer-refs.d.ts +50 -0
- package/dist/codebase-index/writer-search.d.ts +30 -0
- package/dist/codebase-index/writer.d.ts +2 -320
- package/dist/edit.js +8602 -349
- package/dist/exec.js +73 -20
- package/dist/fetch.js +11 -9
- package/dist/format.js +14 -8
- package/dist/glob.js +5 -1
- package/dist/grep.js +19 -8
- package/dist/index.d.ts +3 -1
- package/dist/index.js +6178 -4037
- package/dist/install.js +14 -8
- package/dist/json.js +88 -15
- package/dist/kanban-board-actions.d.ts +4 -0
- package/dist/kanban-lifecycle-actions.d.ts +4 -0
- package/dist/kanban-serializer.d.ts +21 -0
- package/dist/kanban.js +985 -1034
- package/dist/languages/index.js +14 -8
- package/dist/lint.js +14 -8
- package/dist/logs.js +13 -3
- package/dist/next-steps.d.ts +8 -0
- package/dist/next-steps.js +18 -0
- package/dist/outdated.js +14 -8
- package/dist/pack.js +11461 -9304
- package/dist/patch.js +8345 -78
- package/dist/plan.js +1231 -1281
- package/dist/process-registry.js +14 -8
- package/dist/ps-slash.js +65 -30
- package/dist/read.js +822 -937
- package/dist/replace.js +8494 -224
- package/dist/search.js +21 -15
- package/dist/security-ast-scan-tool.d.ts +43 -0
- package/dist/session-kanban-graph.d.ts +9 -0
- package/dist/session-kanban-sync.d.ts +31 -0
- package/dist/session-kanban.d.ts +5 -141
- package/dist/session-kanban.js +367 -360
- package/dist/task.js +1157 -1207
- package/dist/test.js +14 -8
- package/dist/todo.js +2187 -2237
- package/dist/tool-diff.js +6 -1
- package/dist/tool-summary.js +4 -2
- package/dist/tool-tier.js +11469 -9304
- package/dist/typecheck.js +14 -8
- package/dist/write.js +8425 -160
- package/package.json +7 -7
|
@@ -54,7 +54,7 @@ export type WriterSymbolGraphRow = {
|
|
|
54
54
|
signature: string;
|
|
55
55
|
scope: string;
|
|
56
56
|
};
|
|
57
|
-
export declare function buildSymbolGraphNodes(symById: Map<number, WriterSymbolGraphRow>, relatedIds: Set<number>,
|
|
57
|
+
export declare function buildSymbolGraphNodes(symById: Map<number, WriterSymbolGraphRow>, relatedIds: Set<number>, localFiles: ReadonlySet<string> | string, packageOf: (file: string) => string): GraphNode[];
|
|
58
58
|
export type WeightedEdgeAccumulator = {
|
|
59
59
|
weight: number;
|
|
60
60
|
types: Map<string, number>;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import type { Ref, Symbol as IndexSymbol } from './schema.js';
|
|
2
2
|
export declare function escapeLike(value: string): string;
|
|
3
|
+
/** Normalize an indexed or user-supplied file path for comparison. */
|
|
4
|
+
export declare function posixIndexPath(file: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* SQL predicate that matches a stored `file` column against a user-supplied
|
|
7
|
+
* path. Agents pass project-relative paths (`src/calc.ts`); the index stores
|
|
8
|
+
* absolute OS paths. Exact, slash-normalized, and suffix matches are accepted.
|
|
9
|
+
*/
|
|
10
|
+
export declare function indexedFileMatchSql(column?: string): string;
|
|
11
|
+
/** Bind values for {@link indexedFileMatchSql}: exact, posix, suffix-LIKE. */
|
|
12
|
+
export declare function indexedFileMatchArgs(file: string): [string, string, string];
|
|
13
|
+
/** True when a stored file path belongs to a package name or path fragment. */
|
|
14
|
+
export declare function matchesIndexedPackageFilter(storedFile: string, packageLabel: string, filter: string): boolean;
|
|
3
15
|
export declare function assignRefsToSymbols(refs: Ref[], symbols: IndexSymbol[]): Ref[];
|
|
4
16
|
/**
|
|
5
17
|
* Resolve the per-project index directory. By default it lives under the
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { FileMeta, Symbol as IndexSymbol, Ref, SymbolLang } from './schema.js';
|
|
3
|
+
export declare function commitBatchWithStatement(stmtFn: (sql: string) => ReturnType<DatabaseSync['prepare']>, maxSqlVars: number, ftsAvailable: boolean, vectorsAvailable: boolean, allocateSymbolIds: (count: number) => number, invalidateIncomingRefsForFiles: (files: readonly string[]) => Set<string>, resolveRefsForNamesUnsafe: (names: Iterable<string>) => number, entries: Array<{
|
|
4
|
+
file: string;
|
|
5
|
+
lang: SymbolLang;
|
|
6
|
+
symbols: IndexSymbol[];
|
|
7
|
+
refs: Ref[];
|
|
8
|
+
mtimeMs: number;
|
|
9
|
+
symbolCount: number;
|
|
10
|
+
contentHash?: string | undefined;
|
|
11
|
+
}>, options?: {
|
|
12
|
+
deleteForFiles?: string[] | undefined;
|
|
13
|
+
}): IndexSymbol[];
|
|
14
|
+
export declare function replaceEmptyFileWithStatement(stmtFn: (sql: string) => ReturnType<DatabaseSync['prepare']>, ftsAvailable: boolean, vectorsAvailable: boolean, invalidateIncomingRefsForFiles: (files: readonly string[]) => Set<string>, resolveRefsForNamesUnsafe: (names: Iterable<string>) => number, meta: FileMeta): void;
|
|
15
|
+
export declare function insertSymbolsWithStatement(stmtFn: (sql: string) => ReturnType<DatabaseSync['prepare']>, maxSqlVars: number, ftsAvailable: boolean, vectorsAvailable: boolean, allocateSymbolIds: (count: number) => number, symbols: IndexSymbol[]): IndexSymbol[];
|
|
16
|
+
export declare function deleteSymbolsForFileWithStatement(stmtFn: (sql: string) => ReturnType<DatabaseSync['prepare']>, ftsAvailable: boolean, vectorsAvailable: boolean, invalidateIncomingRefsForFiles: (files: readonly string[]) => Set<string>, resolveRefsForNamesUnsafe: (names: Iterable<string>) => number, file: string): void;
|
|
17
|
+
export declare function deleteFileWithStatement(stmtFn: (sql: string) => ReturnType<DatabaseSync['prepare']>, ftsAvailable: boolean, vectorsAvailable: boolean, invalidateIncomingRefsForFiles: (files: readonly string[]) => Set<string>, resolveRefsForNamesUnsafe: (names: Iterable<string>) => number, file: string): void;
|
|
18
|
+
export declare function upsertFileWithStatement(stmtFn: (sql: string) => ReturnType<DatabaseSync['prepare']>, meta: FileMeta): void;
|
|
19
|
+
export declare function setFilePackagesWithStatement(stmtFn: (sql: string) => ReturnType<DatabaseSync['prepare']>, entries: ReadonlyMap<string, string>): void;
|
|
20
|
+
export declare function applyImportResolutionsWithStatement(db: DatabaseSync, stmtFn: (sql: string) => ReturnType<DatabaseSync['prepare']>, maxSqlVars: number, resolutions: ReadonlyArray<{
|
|
21
|
+
fromFile: string;
|
|
22
|
+
lang: string;
|
|
23
|
+
module: string;
|
|
24
|
+
toFile: string;
|
|
25
|
+
}>): number;
|
|
26
|
+
//# sourceMappingURL=writer-mutations.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export declare const FAMILY_MATCH_SQL = "(\n sym.lang = refs.lang\n OR EXISTS (\n SELECT 1 FROM lang_family lf1\n JOIN lang_family lf2 ON lf1.family = lf2.family\n WHERE lf1.lang = sym.lang AND lf2.lang = refs.lang\n )\n OR ? IN (\n SELECT family FROM lang_family WHERE lang = refs.lang\n )\n)";
|
|
2
|
+
export declare function getNamespaceDeclarationsWithStatement(stmtFn: (sql: string) => {
|
|
3
|
+
all: () => unknown[];
|
|
4
|
+
}): Array<{
|
|
5
|
+
name: string;
|
|
6
|
+
file: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function getFilePackagesWithStatement(stmtFn: (sql: string) => {
|
|
9
|
+
all: () => unknown[];
|
|
10
|
+
}): Map<string, string>;
|
|
11
|
+
export declare function getUnresolvedImportsWithStatement(stmtFn: (sql: string) => {
|
|
12
|
+
all: (...args: (string | number)[]) => unknown[];
|
|
13
|
+
}, maxSqlVars: number, onlyFiles?: readonly string[]): Array<{
|
|
14
|
+
fromFile: string;
|
|
15
|
+
lang: string;
|
|
16
|
+
module: string;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function getAllResolvedRefsWithStatement(stmtFn: (sql: string) => {
|
|
19
|
+
all: () => unknown[];
|
|
20
|
+
}): Array<{
|
|
21
|
+
fromId: number;
|
|
22
|
+
toId: number;
|
|
23
|
+
callType: string;
|
|
24
|
+
}>;
|
|
25
|
+
export declare function getAllImportRefsWithStatement(stmtFn: (sql: string) => {
|
|
26
|
+
all: () => unknown[];
|
|
27
|
+
}): Array<{
|
|
28
|
+
sourceFile: string | null;
|
|
29
|
+
toName: string;
|
|
30
|
+
toId: number | null;
|
|
31
|
+
callType: string;
|
|
32
|
+
line: number;
|
|
33
|
+
}>;
|
|
34
|
+
export declare function resolveRefsWithStatement(stmtFn: (sql: string) => {
|
|
35
|
+
run: (...args: (string | number)[]) => unknown;
|
|
36
|
+
}): number;
|
|
37
|
+
export declare function applyImportResolutionsWithStatement(db: {
|
|
38
|
+
exec: (sql: string) => unknown;
|
|
39
|
+
}, stmtFn: (sql: string) => {
|
|
40
|
+
run: (...args: string[]) => unknown;
|
|
41
|
+
}, runWithRetry: <T>(fn: () => T) => T, maxSqlVars: number, resolutions: ReadonlyArray<{
|
|
42
|
+
fromFile: string;
|
|
43
|
+
lang: string;
|
|
44
|
+
module: string;
|
|
45
|
+
toFile: string;
|
|
46
|
+
}>): number;
|
|
47
|
+
export declare function resolveRefsForNamesUnsafe(stmtFn: (sql: string) => {
|
|
48
|
+
run: (...args: (string | number)[]) => unknown;
|
|
49
|
+
}, maxSqlVars: number, names: Iterable<string>): number;
|
|
50
|
+
//# sourceMappingURL=writer-refs.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Bm25Index } from './bm25.js';
|
|
2
|
+
import type { SearchResult } from './schema.js';
|
|
3
|
+
import { type WriterSearchFilter } from './writer-search-helpers.js';
|
|
4
|
+
export declare function searchWithStatement(stmtFn: (sql: string) => {
|
|
5
|
+
all: (...args: (string | number)[]) => unknown[];
|
|
6
|
+
}, query: string, filter?: WriterSearchFilter, opts?: {
|
|
7
|
+
limit?: number | undefined;
|
|
8
|
+
}): SearchResult[];
|
|
9
|
+
export declare function countSearchWithStatement(stmtFn: (sql: string) => {
|
|
10
|
+
get: (...args: (string | number)[]) => unknown;
|
|
11
|
+
}, query: string, filter?: WriterSearchFilter | undefined): number;
|
|
12
|
+
export declare function searchRankedWithStatement(stmtFn: (sql: string) => {
|
|
13
|
+
all: (...args: (string | number)[]) => unknown[];
|
|
14
|
+
get: (...args: (string | number)[]) => unknown;
|
|
15
|
+
}, searchFn: (query: string, filter?: WriterSearchFilter, opts?: {
|
|
16
|
+
limit?: number | undefined;
|
|
17
|
+
}) => SearchResult[], ftsAvailable: boolean, vectorsAvailable: boolean, getOrBuildBm25: () => Bm25Index, query: string, filter: WriterSearchFilter | undefined, limit: number): {
|
|
18
|
+
results: SearchResult[];
|
|
19
|
+
total: number;
|
|
20
|
+
};
|
|
21
|
+
export declare function searchRankedFallbackWithStatement(stmtFn: (sql: string) => {
|
|
22
|
+
all: (...args: (string | number)[]) => unknown[];
|
|
23
|
+
get: (...args: (string | number)[]) => unknown;
|
|
24
|
+
}, searchFn: (query: string, filter?: WriterSearchFilter, opts?: {
|
|
25
|
+
limit?: number | undefined;
|
|
26
|
+
}) => SearchResult[], getOrBuildBm25: () => Bm25Index, query: string, filter: WriterSearchFilter | undefined, limit: number): {
|
|
27
|
+
results: SearchResult[];
|
|
28
|
+
total: number;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=writer-search.d.ts.map
|
|
@@ -1,194 +1,53 @@
|
|
|
1
1
|
import type { CallSite, CodeMapGraph, FileMeta, IndexStats, Symbol as IndexSymbol, Ref, SearchResult, SymbolKind, SymbolLang } from './schema.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { WriterSearchFilter } from './writer-search-helpers.js';
|
|
3
3
|
import { StorePool } from './writer-store-pool.js';
|
|
4
4
|
export { codebaseIndexDirOverride, resolveIndexDir } from './writer-helpers.js';
|
|
5
5
|
export { StorePool } from './writer-store-pool.js';
|
|
6
6
|
export declare class IndexStore {
|
|
7
7
|
private db;
|
|
8
|
-
/**
|
|
9
|
-
* True while an index run owns one outer SQLite transaction. Individual
|
|
10
|
-
* writer methods normally protect themselves with BEGIN/COMMIT, but during
|
|
11
|
-
* a refresh they join this transaction so readers observe either the last
|
|
12
|
-
* completed index or the next completed index, never an in-between batch.
|
|
13
|
-
*/
|
|
14
8
|
private atomicIndexUpdateActive;
|
|
15
9
|
private writeSavepointSequence;
|
|
16
|
-
/** Absolute path to this project's index directory. */
|
|
17
10
|
private readonly indexDir;
|
|
18
|
-
/**
|
|
19
|
-
* True when the SQLite build provides FTS5 (Node's bundled SQLite does).
|
|
20
|
-
* When false, ranked search falls back to the LIKE + in-process BM25 path.
|
|
21
|
-
*/
|
|
22
11
|
private ftsAvailable;
|
|
23
|
-
/**
|
|
24
|
-
* Phase 3: true when the `symbol_vectors` table was created successfully.
|
|
25
|
-
* When false, hybrid search skips the vector pass and falls back to FTS5
|
|
26
|
-
* (or LIKE) only.
|
|
27
|
-
*/
|
|
28
12
|
private vectorsAvailable;
|
|
29
|
-
/**
|
|
30
|
-
* Cache of prepared statements keyed by their SQL text. `DatabaseSync`
|
|
31
|
-
* compiles SQL on every `.prepare()` call; for the fixed-SQL methods
|
|
32
|
-
* (upsertFile, getFileMeta, deleteFile, insertRefs, …) that runs thousands
|
|
33
|
-
* of times during a full reindex. `StatementSync` objects are reusable
|
|
34
|
-
* across calls on the same connection, so we compile each distinct SQL once
|
|
35
|
-
* and reuse it. Cleared in {@link close} when the connection is torn down.
|
|
36
|
-
*/
|
|
37
13
|
private readonly stmtCache;
|
|
38
|
-
/**
|
|
39
|
-
* Cached full-corpus BM25 index for the FTS5-unavailable fallback path.
|
|
40
|
-
* Built lazily on the first `searchRankedFallback` call and invalidated
|
|
41
|
-
* (via `bm25Dirty`) whenever the `symbols` table is mutated. Computing
|
|
42
|
-
* IDF over the full corpus is also more correct than the old per-query
|
|
43
|
-
* candidate-subset IDF.
|
|
44
|
-
*
|
|
45
|
-
* Cache-lifecycle invariants (single source of truth lives at the
|
|
46
|
-
* `invalidateBm25()` helper — see its docblock for the "every mutation
|
|
47
|
-
* MUST call this" contract):
|
|
48
|
-
* - declaration: this field + `bm25Dirty` (here)
|
|
49
|
-
* - invalidation: `invalidateBm25()` flips the flag and nulls the cache
|
|
50
|
-
* - build: `getOrBuildBm25()` rebuilds against current `symbols` rows
|
|
51
|
-
* - teardown: `close()` resets the flag and nulls the cache
|
|
52
|
-
*/
|
|
53
14
|
private bm25Cache;
|
|
54
15
|
private bm25Dirty;
|
|
55
|
-
/**
|
|
56
|
-
* Prepare-once helper: compile `sql` on first use, reuse thereafter.
|
|
57
|
-
*
|
|
58
|
-
* Bounded LRU rather than an open Map. The cache is keyed by SQL TEXT, and
|
|
59
|
-
* the fallback search builder emits one `text LIKE ?` clause per query token
|
|
60
|
-
* — so the SQL varies with the token count and a stream of differently-sized
|
|
61
|
-
* queries grew the cache without limit. Sage's store already bounds its
|
|
62
|
-
* equivalent at 128 (WS-096).
|
|
63
|
-
*
|
|
64
|
-
* Re-inserting on a hit keeps the hot fixed-SQL statements (upsertFile,
|
|
65
|
-
* insertRefs, …) at the young end, so a burst of one-off search SQL evicts
|
|
66
|
-
* itself rather than the reindex hot path.
|
|
67
|
-
*/
|
|
68
16
|
private stmt;
|
|
69
17
|
constructor(projectRoot: string, opts?: {
|
|
70
18
|
indexDir?: string | undefined;
|
|
71
19
|
});
|
|
72
20
|
runWithRetry<T>(fn: () => T): T;
|
|
73
|
-
/** Run a complete index mutation as one WAL-visible publication. */
|
|
74
21
|
runAtomicIndexUpdate<T>(job: () => Promise<T>): Promise<T>;
|
|
75
|
-
/**
|
|
76
|
-
* Begin a method-local transaction. Inside an atomic index publication a
|
|
77
|
-
* SAVEPOINT preserves the old per-batch rollback boundary, which is needed
|
|
78
|
-
* when commitBatch falls back to per-file writes after one batch fails.
|
|
79
|
-
*/
|
|
80
22
|
private beginWriteTransaction;
|
|
81
23
|
private commitWriteTransaction;
|
|
82
24
|
private rollbackWriteTransaction;
|
|
83
|
-
/**
|
|
84
|
-
* Mirror the in-process language→family map into SQLite.
|
|
85
|
-
*
|
|
86
|
-
* Rewritten on every open rather than only on schema bumps: the mapping is
|
|
87
|
-
* static lookup data, so a code-side change (a new language, a language
|
|
88
|
-
* moving families) must take effect without forcing a full reindex.
|
|
89
|
-
*/
|
|
90
25
|
private seedLangFamilies;
|
|
91
|
-
/**
|
|
92
|
-
* Add any column the current schema expects but the on-disk table lacks.
|
|
93
|
-
*
|
|
94
|
-
* `CREATE TABLE IF NOT EXISTS` silently keeps an existing table's old shape,
|
|
95
|
-
* and the version check above only rebuilds on a version *mismatch*. That
|
|
96
|
-
* leaves a real gap: several wstack processes share this database, and while
|
|
97
|
-
* a version upgrade is rolling out one of them may still be running the
|
|
98
|
-
* previous build. That older process sees the newer version number, drops the
|
|
99
|
-
* tables, and recreates them from *its* DDL — without the newer columns —
|
|
100
|
-
* while the metadata row still reads the new version. Every later query for
|
|
101
|
-
* one of those columns then fails with `no such column`, and no amount of
|
|
102
|
-
* reindexing fixes it, because the version numbers already agree.
|
|
103
|
-
*
|
|
104
|
-
* Repairing column-by-column makes the schema self-healing from any of those
|
|
105
|
-
* states. Table and column names are compile-time literals from this module,
|
|
106
|
-
* never user input.
|
|
107
|
-
*/
|
|
108
26
|
private repairMissingColumns;
|
|
109
27
|
private initSchema;
|
|
110
28
|
private static readonly NEXT_SYMBOL_ID_KEY;
|
|
111
|
-
/** Stay under typical SQLite SQLITE_MAX_VARIABLE_NUMBER (often 999). */
|
|
112
29
|
private static readonly MAX_SQL_VARS;
|
|
113
|
-
/**
|
|
114
|
-
* Correlated predicate: the ref in `refs` and the candidate symbol aliased
|
|
115
|
-
* `sym` belong to the same language family — or the ref carries no language,
|
|
116
|
-
* in which case the wildcard bind matches everything.
|
|
117
|
-
*
|
|
118
|
-
* Each textual occurrence consumes one `?` bind of {@link LANG_FAMILY_WILDCARD}.
|
|
119
|
-
*/
|
|
120
|
-
private static readonly FAMILY_MATCH_SQL;
|
|
121
|
-
/**
|
|
122
|
-
* Ensure `metadata.next_symbol_id` exists. Safe to call outside a write
|
|
123
|
-
* transaction on open; the first concurrent writer under BEGIN IMMEDIATE
|
|
124
|
-
* re-reads and advances the counter atomically.
|
|
125
|
-
*/
|
|
126
30
|
private ensureNextSymbolIdSeeded;
|
|
127
|
-
/**
|
|
128
|
-
* Reserve `count` consecutive symbol ids. MUST run inside BEGIN IMMEDIATE
|
|
129
|
-
* so concurrent indexers cannot hand out overlapping ranges.
|
|
130
|
-
*/
|
|
131
31
|
private allocateSymbolIds;
|
|
132
|
-
/**
|
|
133
|
-
* Disconnect inbound refs before their target symbols are replaced and
|
|
134
|
-
* return the affected names for scoped re-resolution.
|
|
135
|
-
*
|
|
136
|
-
* This also repairs a long-standing dangling-id edge case: `refs.to_id` has
|
|
137
|
-
* no physical FK, so deleting a symbol previously left callers pointing at a
|
|
138
|
-
* non-existent row.
|
|
139
|
-
*/
|
|
140
32
|
private invalidateIncomingRefsForFiles;
|
|
141
|
-
/** Resolve only refs whose target names may have changed. */
|
|
142
33
|
private resolveRefsForNamesUnsafe;
|
|
143
|
-
/**
|
|
144
|
-
* Insert symbols, assigning IDs atomically inside `BEGIN IMMEDIATE` /
|
|
145
|
-
* `COMMIT`. Id ranges come from the `next_symbol_id` metadata counter
|
|
146
|
-
* (O(1)); multi-row INSERT amortizes bind overhead for large files.
|
|
147
|
-
*
|
|
148
|
-
* @returns The symbols array with `id` fields populated so the caller can
|
|
149
|
-
* use them for refs without re-reading from the DB.
|
|
150
|
-
*/
|
|
151
34
|
insertSymbols(symbols: IndexSymbol[]): IndexSymbol[];
|
|
152
35
|
deleteSymbolsForFile(file: string): void;
|
|
153
|
-
/**
|
|
154
|
-
* Remove every trace of a file (refs, symbols, FTS rows, file meta). Used
|
|
155
|
-
* when a source file disappears between index runs — previously this only
|
|
156
|
-
* dropped the `files` row, leaving its symbols orphaned but still searchable.
|
|
157
|
-
*/
|
|
158
36
|
deleteFile(file: string): void;
|
|
159
37
|
upsertFile(meta: FileMeta): void;
|
|
160
38
|
getFileMeta(file: string): FileMeta | null;
|
|
161
39
|
getAllFileMetas(): FileMeta[];
|
|
162
|
-
/** Store the Code Atlas grouping label for each indexed file. */
|
|
163
40
|
setFilePackages(entries: ReadonlyMap<string, string>): void;
|
|
164
|
-
/**
|
|
165
|
-
* Every indexed `namespace`/`module` declaration, for ecosystems whose import
|
|
166
|
-
* specifiers name a namespace rather than a path (C#, PHP, Elixir, Haskell).
|
|
167
|
-
* Ordered so the resolver's choice among duplicate declarations is stable.
|
|
168
|
-
*/
|
|
169
41
|
getNamespaceDeclarations(): Array<{
|
|
170
42
|
name: string;
|
|
171
43
|
file: string;
|
|
172
44
|
}>;
|
|
173
|
-
/** `file → package` for every indexed file that has a label. */
|
|
174
45
|
getFilePackages(): Map<string, string>;
|
|
175
|
-
/**
|
|
176
|
-
* Distinct `(fromFile, lang, module)` triples needing module resolution.
|
|
177
|
-
*
|
|
178
|
-
* Distinct rather than per-ref because resolution depends only on these three
|
|
179
|
-
* values: a file importing the same module twenty times resolves it once.
|
|
180
|
-
*/
|
|
181
46
|
getUnresolvedImports(onlyFiles?: readonly string[]): Array<{
|
|
182
47
|
fromFile: string;
|
|
183
48
|
lang: string;
|
|
184
49
|
module: string;
|
|
185
50
|
}>;
|
|
186
|
-
/**
|
|
187
|
-
* Write resolved import targets back onto `refs.to_file`.
|
|
188
|
-
*
|
|
189
|
-
* Applied through a temp table and a single UPDATE: one statement per
|
|
190
|
-
* resolution would mean thousands of round-trips on a first index.
|
|
191
|
-
*/
|
|
192
51
|
applyImportResolutions(resolutions: ReadonlyArray<{
|
|
193
52
|
fromFile: string;
|
|
194
53
|
lang: string;
|
|
@@ -198,111 +57,25 @@ export declare class IndexStore {
|
|
|
198
57
|
search(query: string, filter?: WriterSearchFilter, opts?: {
|
|
199
58
|
limit?: number | undefined;
|
|
200
59
|
}): SearchResult[];
|
|
201
|
-
|
|
202
|
-
private buildSearchWhere;
|
|
203
|
-
private countSearch;
|
|
204
|
-
/**
|
|
205
|
-
* Ranked search — the one-stop query the codebase-search tool and plug-lsp
|
|
206
|
-
* use. With FTS5 this is a single indexed `MATCH` ranked by SQLite's native
|
|
207
|
-
* `bm25()` with a built-in `snippet()`; without FTS5 it falls back to the
|
|
208
|
-
* legacy LIKE scan + in-process BM25 (identical semantics, slower).
|
|
209
|
-
*
|
|
210
|
-
* Tokens are matched as prefixes (`"tok"*`), mirroring the old
|
|
211
|
-
* `LIKE '%tok%'` recall for the common symbol-search shapes ("user" finds
|
|
212
|
-
* "users", camelCase-split text makes "complex" find "complexOperation").
|
|
213
|
-
*/
|
|
60
|
+
countSearch(query: string, filter?: WriterSearchFilter | undefined): number;
|
|
214
61
|
searchRanked(query: string, filter: WriterSearchFilter | undefined, limit: number): {
|
|
215
62
|
results: SearchResult[];
|
|
216
63
|
total: number;
|
|
217
64
|
};
|
|
218
|
-
/**
|
|
219
|
-
* Invalidate the cached BM25 index.
|
|
220
|
-
*
|
|
221
|
-
* **Contract: every method that mutates `symbols` MUST call this before
|
|
222
|
-
* returning.** (`refs` mutations do not affect the BM25 fallback because
|
|
223
|
-
* the corpus is built from `symbols.text` via `getAllIndexable()` and the
|
|
224
|
-
* BM25 score is filtered by the LIKE-selected candidate set in
|
|
225
|
-
* `searchRankedFallback`.) Today the call sites are `repairDrift`,
|
|
226
|
-
* `insertSymbols`, `deleteSymbolsForFile`, `deleteFile`, `clearAll`, and
|
|
227
|
-
* `commitBatch`. A future mutation that adds a new write path (e.g.
|
|
228
|
-
* `renameFile`, `updateSignature`) MUST also call this — otherwise the
|
|
229
|
-
* FTS5-unavailable fallback will serve stale search results. The
|
|
230
|
-
* `close()` reset at L1820-1821 tears the cache down on store shutdown,
|
|
231
|
-
* which is the only legitimate place that flips the flag outside this
|
|
232
|
-
* helper.
|
|
233
|
-
*
|
|
234
|
-
* Called *before* `runWithRetry` on purpose: if the write fails all
|
|
235
|
-
* retries the flag stays set, forcing a rebuild on the next search rather
|
|
236
|
-
* than trusting a cache that may not reflect the intended mutation.
|
|
237
|
-
* Do not move this inside the retry closure.
|
|
238
|
-
*/
|
|
239
65
|
private invalidateBm25;
|
|
240
|
-
/**
|
|
241
|
-
* Return the cached full-corpus BM25 index, rebuilding it only when the
|
|
242
|
-
* symbols table has been mutated since the last build. The full-corpus IDF
|
|
243
|
-
* is more correct than the old per-query candidate-subset IDF, and the
|
|
244
|
-
* amortized build cost drops from O(symbols × tokens) per search to once
|
|
245
|
-
* per write batch.
|
|
246
|
-
*
|
|
247
|
-
* Note: the first call after a long idle (or on a freshly opened store)
|
|
248
|
-
* pays the full corpus rebuild synchronously on the search path. For a
|
|
249
|
-
* 5 500+ symbol corpus this is a visible one-time latency spike.
|
|
250
|
-
*/
|
|
251
66
|
private getOrBuildBm25;
|
|
252
|
-
/** Legacy ranked path: LIKE candidates + in-process BM25 + JS snippets. */
|
|
253
|
-
private searchRankedFallback;
|
|
254
67
|
getAllIndexable(): Array<{
|
|
255
68
|
id: number;
|
|
256
69
|
text: string;
|
|
257
70
|
}>;
|
|
258
|
-
/**
|
|
259
|
-
* Largest symbol id currently in the table (0 when empty). New ids must be
|
|
260
|
-
* allocated from this, NOT from `COUNT(*)`: incremental reindexes delete a
|
|
261
|
-
* changed file's rows, so the row count drops below the max id and a
|
|
262
|
-
* count-based id would collide with a surviving row (UNIQUE constraint on
|
|
263
|
-
* `symbols.id`). Ids may have gaps — that is fine.
|
|
264
|
-
*/
|
|
265
71
|
getMaxSymbolId(): number;
|
|
266
72
|
getStats(): IndexStats;
|
|
267
73
|
setLastIndexed(ts: number): void;
|
|
268
74
|
getMetadata(key: string): string | undefined;
|
|
269
75
|
setMetadata(key: string, value: string): void;
|
|
270
76
|
clearAll(): void;
|
|
271
|
-
/**
|
|
272
|
-
* Insert cross-references for a given source symbol id.
|
|
273
|
-
* Replaces any existing refs from the same source (idempotent on re-index).
|
|
274
|
-
*/
|
|
275
77
|
insertRefs(fromId: number, refs: Ref[]): void;
|
|
276
|
-
/**
|
|
277
|
-
* Bulk-insert refs for many source symbols in a single transaction.
|
|
278
|
-
*
|
|
279
|
-
* Unlike {@link insertRefs} this does NOT delete per source id — the caller
|
|
280
|
-
* (the indexer) has already cleared stale refs for the file via
|
|
281
|
-
* {@link deleteRefsForFile}, so the per-source DELETE would be redundant work
|
|
282
|
-
* repeated once per symbol. One transaction for the whole file instead of one
|
|
283
|
-
* per symbol turns an O(symbols) transaction count into O(1).
|
|
284
|
-
*
|
|
285
|
-
* Each ref's own {@link Ref.fromId} is used; pass an empty array to no-op.
|
|
286
|
-
*/
|
|
287
78
|
insertRefsBatch(refs: Ref[]): void;
|
|
288
|
-
/**
|
|
289
|
-
* Commit a batch of file-level symbol/refs/upserts in a single transaction.
|
|
290
|
-
*
|
|
291
|
-
* Used by the indexer to amortize SQLite commit overhead across many files.
|
|
292
|
-
* Before this, the indexer issued one transaction per file (BEGIN IMMEDIATE
|
|
293
|
-
* for symbols, plus per-file deletes and an upsertFile call), so a 20-file
|
|
294
|
-
* parallel batch cost ~5+ transactions × 20 files = 100+ commits. With
|
|
295
|
-
* this entry point we do exactly one BEGIN/COMMIT per parallel batch.
|
|
296
|
-
*
|
|
297
|
-
* Each entry must already be a fully-parsed FileSymbols (symbols + refs).
|
|
298
|
-
* The caller is responsible for the per-file prefix accounting
|
|
299
|
-
* (refsByLine → flat list with `fromId` populated). `deleteForFiles` lets
|
|
300
|
-
* the caller clear stale symbols/refs for any files being re-indexed before
|
|
301
|
-
* the inserts run (required to keep refs → symbols FK invariants).
|
|
302
|
-
*
|
|
303
|
-
* Returns the symbols back with their assigned `id` (same shape as
|
|
304
|
-
* {@link insertSymbols}) so callers can build final per-file results.
|
|
305
|
-
*/
|
|
306
79
|
commitBatch(entries: Array<{
|
|
307
80
|
file: string;
|
|
308
81
|
lang: SymbolLang;
|
|
@@ -314,119 +87,45 @@ export declare class IndexStore {
|
|
|
314
87
|
}>, options?: {
|
|
315
88
|
deleteForFiles?: string[] | undefined;
|
|
316
89
|
}): IndexSymbol[];
|
|
317
|
-
/**
|
|
318
|
-
* Delete all refs whose source symbols are in a given file.
|
|
319
|
-
* Used when re-indexing a file to clear stale refs.
|
|
320
|
-
*/
|
|
321
90
|
deleteRefsForFile(file: string): void;
|
|
322
|
-
/**
|
|
323
|
-
* Resolve `to_name` → `to_id` for all refs that have a name but no id.
|
|
324
|
-
* Call this after all symbols have been inserted to fill in cross-references.
|
|
325
|
-
*
|
|
326
|
-
* A match additionally requires the referencing ref and the target symbol to
|
|
327
|
-
* be in the same {@link LangFamily}. Without that guard a name match is a
|
|
328
|
-
* cross-language accident waiting to happen — `main`, `New`, `Parse` and
|
|
329
|
-
* `Config` are declared in most languages at once, and each collision draws a
|
|
330
|
-
* Code Atlas edge between files that never reference each other. Refs stored
|
|
331
|
-
* without a language keep the old global behaviour via the `'*'` wildcard row.
|
|
332
|
-
*/
|
|
333
91
|
resolveRefs(): number;
|
|
334
92
|
resolveRefsForNames(names: Iterable<string>): number;
|
|
335
|
-
/**
|
|
336
|
-
* Clear symbols/refs for a file and mark it as indexed with zero symbols.
|
|
337
|
-
* Used by the indexer for empty-parse results so three writes share one txn.
|
|
338
|
-
*/
|
|
339
93
|
replaceEmptyFile(meta: FileMeta): void;
|
|
340
|
-
/** Best-effort query planner refresh after a large reindex. */
|
|
341
94
|
optimize(): void;
|
|
342
|
-
/**
|
|
343
|
-
* Reclaim page churn left by repeated force rebuilds.
|
|
344
|
-
*
|
|
345
|
-
* SQLite's DROP/CREATE path makes rebuilds fast but leaves pages on the
|
|
346
|
-
* freelist. Compact only large, materially sparse databases and only when the
|
|
347
|
-
* caller is already on a full-index maintenance path.
|
|
348
|
-
*/
|
|
349
95
|
compactIfNeeded(options?: {
|
|
350
96
|
minBytes?: number;
|
|
351
97
|
minFreeRatio?: number;
|
|
352
98
|
}): boolean;
|
|
353
|
-
/**
|
|
354
|
-
* Find all symbols that reference the named target symbol (incoming callers).
|
|
355
|
-
* Accepts a name instead of an id so the agent doesn't need a prior lookup.
|
|
356
|
-
*/
|
|
357
99
|
findIncomingCallsByName(symbolName: string, file?: string, limit?: number): {
|
|
358
100
|
calls: CallSite[];
|
|
359
101
|
symbolFound: boolean;
|
|
360
102
|
ambiguous: boolean;
|
|
361
103
|
totalMatches: number;
|
|
362
104
|
};
|
|
363
|
-
/**
|
|
364
|
-
* Find all symbols that the named source symbol references (outgoing callees).
|
|
365
|
-
* Accepts a name instead of an id so the agent doesn't need a prior lookup.
|
|
366
|
-
*/
|
|
367
105
|
findOutgoingCallsByName(symbolName: string, file?: string, limit?: number): {
|
|
368
106
|
calls: CallSite[];
|
|
369
107
|
symbolFound: boolean;
|
|
370
108
|
unresolvedCount: number;
|
|
371
109
|
totalMatches: number;
|
|
372
110
|
};
|
|
373
|
-
/**
|
|
374
|
-
* Transitive incoming-call tree: all symbols that transitively call the
|
|
375
|
-
* target, to an unbounded depth (cycle-safe via SQL UNION deduplication).
|
|
376
|
-
* Used by `codebase-incoming-calls` when the caller wants the full call
|
|
377
|
-
* chain rather than just direct callers.
|
|
378
|
-
*/
|
|
379
111
|
findTransitiveIncomingCallsByName(symbolName: string, file?: string, limit?: number): {
|
|
380
112
|
calls: CallSite[];
|
|
381
113
|
symbolFound: boolean;
|
|
382
114
|
ambiguous: boolean;
|
|
383
115
|
totalMatches: number;
|
|
384
116
|
};
|
|
385
|
-
/**
|
|
386
|
-
* Transitive outgoing-call tree: all symbols the target transitively calls.
|
|
387
|
-
* Used by `codebase-outgoing-calls` when the caller wants the full
|
|
388
|
-
* dependency chain rather than just direct callees.
|
|
389
|
-
*/
|
|
390
117
|
findTransitiveOutgoingCallsByName(symbolName: string, file?: string, limit?: number): {
|
|
391
118
|
calls: CallSite[];
|
|
392
119
|
symbolFound: boolean;
|
|
393
120
|
unresolvedCount: number;
|
|
394
121
|
totalMatches: number;
|
|
395
122
|
};
|
|
396
|
-
/**
|
|
397
|
-
* Compute the set of symbol IDs reachable from the given seed IDs using a
|
|
398
|
-
* native SQLite recursive CTE. Used by dead-code detection to replace the
|
|
399
|
-
* in-memory BFS.
|
|
400
|
-
*/
|
|
401
123
|
findReachableSymbolIds(seedIds: number[]): Set<number>;
|
|
402
|
-
/**
|
|
403
|
-
* Find all references TO a given symbol (who calls / uses this symbol?).
|
|
404
|
-
*/
|
|
405
124
|
findRefsTo(symbolId: number): Ref[];
|
|
406
|
-
/**
|
|
407
|
-
* Find all references FROM a given symbol (what does this symbol call/use?).
|
|
408
|
-
*/
|
|
409
125
|
findRefsFrom(symbolId: number): Ref[];
|
|
410
|
-
/**
|
|
411
|
-
* Package-level graph: each workspace package is a node; edges are derived
|
|
412
|
-
* from cross-package symbol references (a symbol in package A references a
|
|
413
|
-
* symbol resolved in package B). Node metadata includes symbol/file counts.
|
|
414
|
-
*/
|
|
415
126
|
getPackageGraph(): CodeMapGraph;
|
|
416
|
-
/**
|
|
417
|
-
* File-level graph for a single package: each file is a node; edges are
|
|
418
|
-
* derived from cross-file symbol references within the package.
|
|
419
|
-
*/
|
|
420
127
|
getFileGraph(packageFilter: string): CodeMapGraph;
|
|
421
|
-
/**
|
|
422
|
-
* Symbol-level graph for a single file: each symbol is a node; edges are
|
|
423
|
-
* derived from intra-file and cross-file symbol references (who calls whom).
|
|
424
|
-
*/
|
|
425
128
|
getSymbolGraph(fileFilter: string): CodeMapGraph;
|
|
426
|
-
/**
|
|
427
|
-
* Returns every symbol in the index. Used by dead-code analysis to
|
|
428
|
-
* build the full symbol universe for the reachability scan.
|
|
429
|
-
*/
|
|
430
129
|
getAllSymbols(): Array<{
|
|
431
130
|
id: number;
|
|
432
131
|
name: string;
|
|
@@ -434,36 +133,19 @@ export declare class IndexStore {
|
|
|
434
133
|
kind: SymbolKind;
|
|
435
134
|
line: number;
|
|
436
135
|
}>;
|
|
437
|
-
/**
|
|
438
|
-
* Returns every resolved reference (to_id IS NOT NULL). Used by
|
|
439
|
-
* dead-code analysis to build the consumer-ship graph. Refs whose
|
|
440
|
-
* target symbol id is null (unresolved imports) are excluded.
|
|
441
|
-
*/
|
|
442
136
|
getAllResolvedRefs(): Array<{
|
|
443
137
|
fromId: number;
|
|
444
138
|
toId: number;
|
|
445
139
|
callType: string;
|
|
446
140
|
}>;
|
|
447
|
-
/**
|
|
448
|
-
* Returns ALL import refs (including unresolved) with their source-file
|
|
449
|
-
* path and resolved target id. Used by the dead-code scan's file-level
|
|
450
|
-
* graph traversal to handle barrel-only entry points where no symbol
|
|
451
|
-
* carries the ref.
|
|
452
|
-
*
|
|
453
|
-
* Refs whose `from_id` doesn't match a known symbol (e.g. pure-barrel
|
|
454
|
-
* files with no declarations) will have `sourceFile === null`.
|
|
455
|
-
*/
|
|
456
141
|
getAllImportRefs(): Array<{
|
|
457
|
-
/** Source-file path (null when the owning symbol can't be resolved). */
|
|
458
142
|
sourceFile: string | null;
|
|
459
143
|
toName: string;
|
|
460
|
-
/** Resolved target symbol id (null when the name couldn't be matched). */
|
|
461
144
|
toId: number | null;
|
|
462
145
|
callType: string;
|
|
463
146
|
line: number;
|
|
464
147
|
}>;
|
|
465
148
|
close(): void;
|
|
466
149
|
}
|
|
467
|
-
/** Process-wide singleton pool. */
|
|
468
150
|
export declare const indexStorePool: StorePool<IndexStore>;
|
|
469
151
|
//# sourceMappingURL=writer.d.ts.map
|