@pratik7368patil/anchor-core 0.1.24 → 0.1.25
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/index.d.ts +108 -4
- package/dist/index.js +369 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1535,6 +1535,10 @@ function calculateCoverage(input) {
|
|
|
1535
1535
|
}
|
|
1536
1536
|
|
|
1537
1537
|
// src/db/database.ts
|
|
1538
|
+
var CODE_WRITE_PROGRESS_INTERVAL = 500;
|
|
1539
|
+
function shouldEmitCodeWriteProgress(current, total) {
|
|
1540
|
+
return current === 0 || current === 1 || current === total || current % CODE_WRITE_PROGRESS_INTERVAL === 0;
|
|
1541
|
+
}
|
|
1538
1542
|
function defaultDatabasePath(cwd) {
|
|
1539
1543
|
return path4.join(cwd, ".anchor", "index.sqlite");
|
|
1540
1544
|
}
|
|
@@ -1902,13 +1906,22 @@ function upsertPullRequest(db, pr, wisdomUnits, regressionEvents = []) {
|
|
|
1902
1906
|
regressions: regressionEvents.length
|
|
1903
1907
|
};
|
|
1904
1908
|
}
|
|
1905
|
-
function replaceCodeIndex(db, repo, codeFiles, codeChunks, skippedFiles, cwd, architecture = { components: [], patterns: [], imports: [] }) {
|
|
1909
|
+
function replaceCodeIndex(db, repo, codeFiles, codeChunks, skippedFiles, cwd, architecture = { components: [], patterns: [], imports: [] }, options = {}) {
|
|
1906
1910
|
initializeSchema(db);
|
|
1907
1911
|
const repoId = ensureRepository(db, repo);
|
|
1908
1912
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1913
|
+
options.onProgress?.({ stage: "writing_code_index", repo, phase: "Inferring test awareness" });
|
|
1909
1914
|
const testAwareness = inferTestAwareness(repo, codeFiles, codeChunks);
|
|
1915
|
+
options.onProgress?.({ stage: "writing_code_index", repo, phase: "Writing code index" });
|
|
1910
1916
|
const transaction = db.transaction(() => {
|
|
1911
1917
|
const existingChunks = db.prepare("SELECT id FROM code_chunks WHERE repo_id = ?").all(repoId);
|
|
1918
|
+
const existingPatternCount = db.prepare("SELECT COUNT(*) AS count FROM architecture_patterns WHERE repo_id = ?").get(repoId).count;
|
|
1919
|
+
options.onProgress?.({
|
|
1920
|
+
stage: "deleting_existing_code_index",
|
|
1921
|
+
repo,
|
|
1922
|
+
chunks: existingChunks.length,
|
|
1923
|
+
patterns: existingPatternCount
|
|
1924
|
+
});
|
|
1912
1925
|
const deleteFts = db.prepare("DELETE FROM code_chunks_fts WHERE chunkId = ?");
|
|
1913
1926
|
for (const row of existingChunks) deleteFts.run(row.id);
|
|
1914
1927
|
db.prepare("DELETE FROM code_chunks WHERE repo_id = ?").run(repoId);
|
|
@@ -1921,7 +1934,13 @@ function replaceCodeIndex(db, repo, codeFiles, codeChunks, skippedFiles, cwd, ar
|
|
|
1921
1934
|
(repo_id, path, language, size_bytes, content_hash, updated_at)
|
|
1922
1935
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
1923
1936
|
);
|
|
1924
|
-
|
|
1937
|
+
options.onProgress?.({
|
|
1938
|
+
stage: "writing_code_files",
|
|
1939
|
+
repo,
|
|
1940
|
+
current: 0,
|
|
1941
|
+
total: codeFiles.length
|
|
1942
|
+
});
|
|
1943
|
+
for (const [index, file] of codeFiles.entries()) {
|
|
1925
1944
|
insertFile.run(
|
|
1926
1945
|
repoId,
|
|
1927
1946
|
file.path,
|
|
@@ -1930,6 +1949,16 @@ function replaceCodeIndex(db, repo, codeFiles, codeChunks, skippedFiles, cwd, ar
|
|
|
1930
1949
|
file.contentHash,
|
|
1931
1950
|
file.updatedAt
|
|
1932
1951
|
);
|
|
1952
|
+
const current = index + 1;
|
|
1953
|
+
if (shouldEmitCodeWriteProgress(current, codeFiles.length)) {
|
|
1954
|
+
options.onProgress?.({
|
|
1955
|
+
stage: "writing_code_files",
|
|
1956
|
+
repo,
|
|
1957
|
+
current,
|
|
1958
|
+
total: codeFiles.length,
|
|
1959
|
+
filePath: file.path
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1933
1962
|
}
|
|
1934
1963
|
const fileRows = db.prepare("SELECT id, path FROM code_files WHERE repo_id = ?").all(repoId);
|
|
1935
1964
|
const fileIds = new Map(fileRows.map((row) => [row.path, row.id]));
|
|
@@ -1944,7 +1973,15 @@ function replaceCodeIndex(db, repo, codeFiles, codeChunks, skippedFiles, cwd, ar
|
|
|
1944
1973
|
(chunkId, sanitizedText, filePath, symbols, language)
|
|
1945
1974
|
VALUES (?, ?, ?, ?, ?)`
|
|
1946
1975
|
);
|
|
1947
|
-
|
|
1976
|
+
options.onProgress?.({
|
|
1977
|
+
stage: "writing_code_chunks",
|
|
1978
|
+
repo,
|
|
1979
|
+
current: 0,
|
|
1980
|
+
total: codeChunks.length,
|
|
1981
|
+
chunks: 0
|
|
1982
|
+
});
|
|
1983
|
+
let writtenChunks = 0;
|
|
1984
|
+
for (const [index, chunk] of codeChunks.entries()) {
|
|
1948
1985
|
const fileId = fileIds.get(chunk.filePath);
|
|
1949
1986
|
if (!fileId) continue;
|
|
1950
1987
|
insertChunk.run(
|
|
@@ -1968,10 +2005,23 @@ function replaceCodeIndex(db, repo, codeFiles, codeChunks, skippedFiles, cwd, ar
|
|
|
1968
2005
|
chunk.symbols.join(" "),
|
|
1969
2006
|
chunk.language ?? ""
|
|
1970
2007
|
);
|
|
2008
|
+
writtenChunks += 1;
|
|
2009
|
+
const current = index + 1;
|
|
2010
|
+
if (shouldEmitCodeWriteProgress(current, codeChunks.length)) {
|
|
2011
|
+
options.onProgress?.({
|
|
2012
|
+
stage: "writing_code_chunks",
|
|
2013
|
+
repo,
|
|
2014
|
+
current,
|
|
2015
|
+
total: codeChunks.length,
|
|
2016
|
+
filePath: chunk.filePath,
|
|
2017
|
+
chunks: writtenChunks
|
|
2018
|
+
});
|
|
2019
|
+
}
|
|
1971
2020
|
}
|
|
1972
|
-
insertTestAwareness(db, repoId, testAwareness.testFiles, testAwareness.testLinks);
|
|
1973
|
-
insertArchitectureData(db, repoId, architecture);
|
|
1974
|
-
insertArchitectureMapEdges(db, repoId, repo, architecture, testAwareness.testLinks);
|
|
2021
|
+
insertTestAwareness(db, repoId, repo, testAwareness.testFiles, testAwareness.testLinks, options);
|
|
2022
|
+
insertArchitectureData(db, repoId, repo, architecture, options);
|
|
2023
|
+
insertArchitectureMapEdges(db, repoId, repo, architecture, testAwareness.testLinks, options);
|
|
2024
|
+
options.onProgress?.({ stage: "writing_code_index", repo, phase: "Updating index state" });
|
|
1975
2025
|
db.prepare(
|
|
1976
2026
|
`INSERT INTO code_index_state (repo, last_indexed_at, indexed_files, code_chunks, skipped_files)
|
|
1977
2027
|
VALUES (?, ?, ?, ?, ?)
|
|
@@ -2019,13 +2069,20 @@ function deleteExistingArchitectureData(db, repoId) {
|
|
|
2019
2069
|
db.prepare("DELETE FROM code_imports WHERE repo_id = ?").run(repoId);
|
|
2020
2070
|
db.prepare("DELETE FROM architecture_map_edges WHERE repo_id = ?").run(repoId);
|
|
2021
2071
|
}
|
|
2022
|
-
function insertArchitectureData(db, repoId, architecture) {
|
|
2072
|
+
function insertArchitectureData(db, repoId, repo, architecture, options = {}) {
|
|
2023
2073
|
const insertImport = db.prepare(
|
|
2024
2074
|
`INSERT INTO code_imports
|
|
2025
2075
|
(repo_id, source_path, specifier, imported_path, imported_symbols_json, kind)
|
|
2026
2076
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
2027
2077
|
);
|
|
2028
|
-
|
|
2078
|
+
options.onProgress?.({
|
|
2079
|
+
stage: "writing_architecture_data",
|
|
2080
|
+
repo,
|
|
2081
|
+
current: 0,
|
|
2082
|
+
total: architecture.imports.length,
|
|
2083
|
+
kind: "imports"
|
|
2084
|
+
});
|
|
2085
|
+
for (const [index, item] of architecture.imports.entries()) {
|
|
2029
2086
|
insertImport.run(
|
|
2030
2087
|
repoId,
|
|
2031
2088
|
item.sourcePath,
|
|
@@ -2034,6 +2091,16 @@ function insertArchitectureData(db, repoId, architecture) {
|
|
|
2034
2091
|
JSON.stringify(item.importedSymbols),
|
|
2035
2092
|
item.kind
|
|
2036
2093
|
);
|
|
2094
|
+
const current = index + 1;
|
|
2095
|
+
if (shouldEmitCodeWriteProgress(current, architecture.imports.length)) {
|
|
2096
|
+
options.onProgress?.({
|
|
2097
|
+
stage: "writing_architecture_data",
|
|
2098
|
+
repo,
|
|
2099
|
+
current,
|
|
2100
|
+
total: architecture.imports.length,
|
|
2101
|
+
kind: "imports"
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2037
2104
|
}
|
|
2038
2105
|
const insertComponent = db.prepare(
|
|
2039
2106
|
`INSERT INTO architecture_components
|
|
@@ -2041,7 +2108,14 @@ function insertArchitectureData(db, repoId, architecture) {
|
|
|
2041
2108
|
confidence, updated_at)
|
|
2042
2109
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
2043
2110
|
);
|
|
2044
|
-
|
|
2111
|
+
options.onProgress?.({
|
|
2112
|
+
stage: "writing_architecture_data",
|
|
2113
|
+
repo,
|
|
2114
|
+
current: 0,
|
|
2115
|
+
total: architecture.components.length,
|
|
2116
|
+
kind: "components"
|
|
2117
|
+
});
|
|
2118
|
+
for (const [index, component] of architecture.components.entries()) {
|
|
2045
2119
|
insertComponent.run(
|
|
2046
2120
|
repoId,
|
|
2047
2121
|
component.path,
|
|
@@ -2054,6 +2128,16 @@ function insertArchitectureData(db, repoId, architecture) {
|
|
|
2054
2128
|
component.confidence,
|
|
2055
2129
|
component.updatedAt
|
|
2056
2130
|
);
|
|
2131
|
+
const current = index + 1;
|
|
2132
|
+
if (shouldEmitCodeWriteProgress(current, architecture.components.length)) {
|
|
2133
|
+
options.onProgress?.({
|
|
2134
|
+
stage: "writing_architecture_data",
|
|
2135
|
+
repo,
|
|
2136
|
+
current,
|
|
2137
|
+
total: architecture.components.length,
|
|
2138
|
+
kind: "components"
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2057
2141
|
}
|
|
2058
2142
|
const insertPattern = db.prepare(
|
|
2059
2143
|
`INSERT INTO architecture_patterns
|
|
@@ -2065,7 +2149,14 @@ function insertArchitectureData(db, repoId, architecture) {
|
|
|
2065
2149
|
`INSERT INTO architecture_patterns_fts (patternId, summary, area, sourceFiles, symbols)
|
|
2066
2150
|
VALUES (?, ?, ?, ?, ?)`
|
|
2067
2151
|
);
|
|
2068
|
-
|
|
2152
|
+
options.onProgress?.({
|
|
2153
|
+
stage: "writing_architecture_data",
|
|
2154
|
+
repo,
|
|
2155
|
+
current: 0,
|
|
2156
|
+
total: architecture.patterns.length,
|
|
2157
|
+
kind: "patterns"
|
|
2158
|
+
});
|
|
2159
|
+
for (const [index, pattern] of architecture.patterns.entries()) {
|
|
2069
2160
|
insertPattern.run(
|
|
2070
2161
|
pattern.id,
|
|
2071
2162
|
repoId,
|
|
@@ -2086,9 +2177,19 @@ function insertArchitectureData(db, repoId, architecture) {
|
|
|
2086
2177
|
pattern.sourceFiles.join(" "),
|
|
2087
2178
|
pattern.symbols.join(" ")
|
|
2088
2179
|
);
|
|
2180
|
+
const current = index + 1;
|
|
2181
|
+
if (shouldEmitCodeWriteProgress(current, architecture.patterns.length)) {
|
|
2182
|
+
options.onProgress?.({
|
|
2183
|
+
stage: "writing_architecture_data",
|
|
2184
|
+
repo,
|
|
2185
|
+
current,
|
|
2186
|
+
total: architecture.patterns.length,
|
|
2187
|
+
kind: "patterns"
|
|
2188
|
+
});
|
|
2189
|
+
}
|
|
2089
2190
|
}
|
|
2090
2191
|
}
|
|
2091
|
-
function insertArchitectureMapEdges(db, repoId, repo, architecture, testLinks) {
|
|
2192
|
+
function insertArchitectureMapEdges(db, repoId, repo, architecture, testLinks, options = {}) {
|
|
2092
2193
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2093
2194
|
const insert = db.prepare(
|
|
2094
2195
|
`INSERT INTO architecture_map_edges
|
|
@@ -2103,11 +2204,40 @@ function insertArchitectureMapEdges(db, repoId, repo, architecture, testLinks) {
|
|
|
2103
2204
|
seen.add(id);
|
|
2104
2205
|
insert.run(id, repoId, repo, sourcePath, targetPath, relationship, weight, now);
|
|
2105
2206
|
};
|
|
2207
|
+
const total = architecture.imports.length + testLinks.length;
|
|
2208
|
+
let current = 0;
|
|
2209
|
+
options.onProgress?.({
|
|
2210
|
+
stage: "writing_architecture_map_edges",
|
|
2211
|
+
repo,
|
|
2212
|
+
current,
|
|
2213
|
+
total,
|
|
2214
|
+
edges: 0
|
|
2215
|
+
});
|
|
2106
2216
|
for (const item of architecture.imports) {
|
|
2107
2217
|
if (item.importedPath) addEdge(item.sourcePath, item.importedPath, "imports", 0.9);
|
|
2218
|
+
current += 1;
|
|
2219
|
+
if (shouldEmitCodeWriteProgress(current, total)) {
|
|
2220
|
+
options.onProgress?.({
|
|
2221
|
+
stage: "writing_architecture_map_edges",
|
|
2222
|
+
repo,
|
|
2223
|
+
current,
|
|
2224
|
+
total,
|
|
2225
|
+
edges: seen.size
|
|
2226
|
+
});
|
|
2227
|
+
}
|
|
2108
2228
|
}
|
|
2109
2229
|
for (const link of testLinks) {
|
|
2110
2230
|
addEdge(link.sourcePath, link.testPath, "tested_by", link.strength);
|
|
2231
|
+
current += 1;
|
|
2232
|
+
if (shouldEmitCodeWriteProgress(current, total)) {
|
|
2233
|
+
options.onProgress?.({
|
|
2234
|
+
stage: "writing_architecture_map_edges",
|
|
2235
|
+
repo,
|
|
2236
|
+
current,
|
|
2237
|
+
total,
|
|
2238
|
+
edges: seen.size
|
|
2239
|
+
});
|
|
2240
|
+
}
|
|
2111
2241
|
}
|
|
2112
2242
|
}
|
|
2113
2243
|
function insertPrCochangeTestLinks(db, repoId, filePaths) {
|
|
@@ -2123,13 +2253,20 @@ function insertPrCochangeTestLinks(db, repoId, filePaths) {
|
|
|
2123
2253
|
for (const testPath of testPaths) insert.run(repoId, sourcePath, testPath);
|
|
2124
2254
|
}
|
|
2125
2255
|
}
|
|
2126
|
-
function insertTestAwareness(db, repoId, testFiles, testLinks) {
|
|
2256
|
+
function insertTestAwareness(db, repoId, repo, testFiles, testLinks, options = {}) {
|
|
2127
2257
|
const insertTestFile = db.prepare(
|
|
2128
2258
|
`INSERT INTO test_files
|
|
2129
2259
|
(repo_id, path, language, size_bytes, content_hash, updated_at)
|
|
2130
2260
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
2131
2261
|
);
|
|
2132
|
-
|
|
2262
|
+
options.onProgress?.({
|
|
2263
|
+
stage: "writing_test_awareness",
|
|
2264
|
+
repo,
|
|
2265
|
+
current: 0,
|
|
2266
|
+
total: testFiles.length,
|
|
2267
|
+
kind: "test_files"
|
|
2268
|
+
});
|
|
2269
|
+
for (const [index, file] of testFiles.entries()) {
|
|
2133
2270
|
insertTestFile.run(
|
|
2134
2271
|
repoId,
|
|
2135
2272
|
file.path,
|
|
@@ -2138,13 +2275,40 @@ function insertTestAwareness(db, repoId, testFiles, testLinks) {
|
|
|
2138
2275
|
file.contentHash,
|
|
2139
2276
|
file.updatedAt
|
|
2140
2277
|
);
|
|
2278
|
+
const current = index + 1;
|
|
2279
|
+
if (shouldEmitCodeWriteProgress(current, testFiles.length)) {
|
|
2280
|
+
options.onProgress?.({
|
|
2281
|
+
stage: "writing_test_awareness",
|
|
2282
|
+
repo,
|
|
2283
|
+
current,
|
|
2284
|
+
total: testFiles.length,
|
|
2285
|
+
kind: "test_files"
|
|
2286
|
+
});
|
|
2287
|
+
}
|
|
2141
2288
|
}
|
|
2142
2289
|
const insertTestLink = db.prepare(
|
|
2143
2290
|
`INSERT INTO test_links (repo_id, source_path, test_path, reason, strength)
|
|
2144
2291
|
VALUES (?, ?, ?, ?, ?)`
|
|
2145
2292
|
);
|
|
2146
|
-
|
|
2293
|
+
options.onProgress?.({
|
|
2294
|
+
stage: "writing_test_awareness",
|
|
2295
|
+
repo,
|
|
2296
|
+
current: 0,
|
|
2297
|
+
total: testLinks.length,
|
|
2298
|
+
kind: "test_links"
|
|
2299
|
+
});
|
|
2300
|
+
for (const [index, link] of testLinks.entries()) {
|
|
2147
2301
|
insertTestLink.run(repoId, link.sourcePath, link.testPath, link.reason, link.strength);
|
|
2302
|
+
const current = index + 1;
|
|
2303
|
+
if (shouldEmitCodeWriteProgress(current, testLinks.length)) {
|
|
2304
|
+
options.onProgress?.({
|
|
2305
|
+
stage: "writing_test_awareness",
|
|
2306
|
+
repo,
|
|
2307
|
+
current,
|
|
2308
|
+
total: testLinks.length,
|
|
2309
|
+
kind: "test_links"
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2148
2312
|
}
|
|
2149
2313
|
}
|
|
2150
2314
|
function recordIndexRun(db, run) {
|
|
@@ -2471,6 +2635,10 @@ function chunkCodeFile(file, options = {}) {
|
|
|
2471
2635
|
import crypto2 from "crypto";
|
|
2472
2636
|
import path6 from "path";
|
|
2473
2637
|
var KNOWN_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".json"];
|
|
2638
|
+
var ARCHITECTURE_PROGRESS_INTERVAL = 250;
|
|
2639
|
+
function shouldEmitProgress(current, total) {
|
|
2640
|
+
return current === 0 || current === 1 || current === total || current % ARCHITECTURE_PROGRESS_INTERVAL === 0;
|
|
2641
|
+
}
|
|
2474
2642
|
function classifyArchitectureArea(filePath, language, content = "") {
|
|
2475
2643
|
const normalized = filePath.replace(/\\/g, "/").toLowerCase();
|
|
2476
2644
|
const basename = path6.basename(normalized);
|
|
@@ -2618,7 +2786,7 @@ function createPattern(input) {
|
|
|
2618
2786
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2619
2787
|
};
|
|
2620
2788
|
}
|
|
2621
|
-
function buildArchitectureIndex(repo, files, chunks) {
|
|
2789
|
+
function buildArchitectureIndex(repo, files, chunks, options = {}) {
|
|
2622
2790
|
const allPaths = files.map((file) => file.path);
|
|
2623
2791
|
const codePaths = new Set(allPaths);
|
|
2624
2792
|
const symbolsByPath = /* @__PURE__ */ new Map();
|
|
@@ -2626,20 +2794,47 @@ function buildArchitectureIndex(repo, files, chunks) {
|
|
|
2626
2794
|
const existing = symbolsByPath.get(chunk.filePath) ?? [];
|
|
2627
2795
|
symbolsByPath.set(chunk.filePath, uniqueStrings([...existing, ...chunk.symbols]).slice(0, 40));
|
|
2628
2796
|
}
|
|
2629
|
-
const imports =
|
|
2630
|
-
|
|
2631
|
-
|
|
2797
|
+
const imports = [];
|
|
2798
|
+
options.onProgress?.({
|
|
2799
|
+
stage: "building_architecture_imports",
|
|
2800
|
+
repo,
|
|
2801
|
+
current: 0,
|
|
2802
|
+
total: files.length,
|
|
2803
|
+
imports: 0
|
|
2804
|
+
});
|
|
2805
|
+
for (const [index, file] of files.entries()) {
|
|
2806
|
+
imports.push(...extractCodeImports(file.path, file.content, codePaths, repo));
|
|
2807
|
+
const current = index + 1;
|
|
2808
|
+
if (shouldEmitProgress(current, files.length)) {
|
|
2809
|
+
options.onProgress?.({
|
|
2810
|
+
stage: "building_architecture_imports",
|
|
2811
|
+
repo,
|
|
2812
|
+
current,
|
|
2813
|
+
total: files.length,
|
|
2814
|
+
filePath: file.path,
|
|
2815
|
+
imports: imports.length
|
|
2816
|
+
});
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2632
2819
|
const importsByPath = /* @__PURE__ */ new Map();
|
|
2633
2820
|
for (const item of imports) {
|
|
2634
2821
|
const existing = importsByPath.get(item.sourcePath) ?? [];
|
|
2635
2822
|
existing.push(item);
|
|
2636
2823
|
importsByPath.set(item.sourcePath, existing);
|
|
2637
2824
|
}
|
|
2638
|
-
const components =
|
|
2825
|
+
const components = [];
|
|
2826
|
+
options.onProgress?.({
|
|
2827
|
+
stage: "building_architecture_components",
|
|
2828
|
+
repo,
|
|
2829
|
+
current: 0,
|
|
2830
|
+
total: files.length,
|
|
2831
|
+
components: 0
|
|
2832
|
+
});
|
|
2833
|
+
for (const [index, file] of files.entries()) {
|
|
2639
2834
|
const area = classifyArchitectureArea(file.path, file.language, file.content);
|
|
2640
2835
|
const fileImports = importsByPath.get(file.path) ?? [];
|
|
2641
2836
|
const symbols = symbolsByPath.get(file.path) ?? [];
|
|
2642
|
-
|
|
2837
|
+
components.push({
|
|
2643
2838
|
repo,
|
|
2644
2839
|
path: file.path,
|
|
2645
2840
|
area,
|
|
@@ -2652,16 +2847,49 @@ function buildArchitectureIndex(repo, files, chunks) {
|
|
|
2652
2847
|
relatedTests: relatedTestsFor(file.path, allPaths),
|
|
2653
2848
|
confidence: area === "unknown" ? 0.45 : 0.82,
|
|
2654
2849
|
updatedAt: file.updatedAt
|
|
2655
|
-
};
|
|
2656
|
-
|
|
2850
|
+
});
|
|
2851
|
+
const current = index + 1;
|
|
2852
|
+
if (shouldEmitProgress(current, files.length)) {
|
|
2853
|
+
options.onProgress?.({
|
|
2854
|
+
stage: "building_architecture_components",
|
|
2855
|
+
repo,
|
|
2856
|
+
current,
|
|
2857
|
+
total: files.length,
|
|
2858
|
+
filePath: file.path,
|
|
2859
|
+
components: components.length
|
|
2860
|
+
});
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2657
2863
|
const componentByPath = new Map(components.map((component) => [component.path, component]));
|
|
2658
|
-
const patterns = [];
|
|
2659
2864
|
const componentsByArea = /* @__PURE__ */ new Map();
|
|
2660
2865
|
for (const component of components) {
|
|
2661
2866
|
const existing = componentsByArea.get(component.area) ?? [];
|
|
2662
2867
|
existing.push(component);
|
|
2663
2868
|
componentsByArea.set(component.area, existing);
|
|
2664
2869
|
}
|
|
2870
|
+
const importDirectionCounts = /* @__PURE__ */ new Map();
|
|
2871
|
+
for (const item of imports) {
|
|
2872
|
+
if (!item.importedPath) continue;
|
|
2873
|
+
const source = componentByPath.get(item.sourcePath);
|
|
2874
|
+
const target = componentByPath.get(item.importedPath);
|
|
2875
|
+
if (!source || !target || source.area === target.area) continue;
|
|
2876
|
+
const key = `${source.area}->${target.area}`;
|
|
2877
|
+
const existing = importDirectionCounts.get(key) ?? { count: 0, files: [], symbols: [] };
|
|
2878
|
+
existing.count += 1;
|
|
2879
|
+
existing.files.push(source.path, target.path);
|
|
2880
|
+
existing.symbols.push(...item.importedSymbols);
|
|
2881
|
+
importDirectionCounts.set(key, existing);
|
|
2882
|
+
}
|
|
2883
|
+
const patterns = [];
|
|
2884
|
+
const patternTotal = componentsByArea.size + importDirectionCounts.size;
|
|
2885
|
+
let patternProgress = 0;
|
|
2886
|
+
options.onProgress?.({
|
|
2887
|
+
stage: "building_architecture_patterns",
|
|
2888
|
+
repo,
|
|
2889
|
+
current: 0,
|
|
2890
|
+
total: patternTotal,
|
|
2891
|
+
patterns: 0
|
|
2892
|
+
});
|
|
2665
2893
|
for (const [area, areaComponents] of componentsByArea.entries()) {
|
|
2666
2894
|
const filesForArea = areaComponents.map((component) => component.path);
|
|
2667
2895
|
const directories = topDirectories(filesForArea);
|
|
@@ -2677,19 +2905,17 @@ function buildArchitectureIndex(repo, files, chunks) {
|
|
|
2677
2905
|
confidence: 0.55 + Math.min(0.3, filesForArea.length * 0.04)
|
|
2678
2906
|
})
|
|
2679
2907
|
);
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
existing.symbols.push(...item.importedSymbols);
|
|
2692
|
-
importDirectionCounts.set(key, existing);
|
|
2908
|
+
patternProgress += 1;
|
|
2909
|
+
if (shouldEmitProgress(patternProgress, patternTotal)) {
|
|
2910
|
+
options.onProgress?.({
|
|
2911
|
+
stage: "building_architecture_patterns",
|
|
2912
|
+
repo,
|
|
2913
|
+
current: patternProgress,
|
|
2914
|
+
total: patternTotal,
|
|
2915
|
+
area,
|
|
2916
|
+
patterns: patterns.length
|
|
2917
|
+
});
|
|
2918
|
+
}
|
|
2693
2919
|
}
|
|
2694
2920
|
for (const [key, value] of importDirectionCounts.entries()) {
|
|
2695
2921
|
const [sourceArea, targetArea] = key.split("->");
|
|
@@ -2704,6 +2930,17 @@ function buildArchitectureIndex(repo, files, chunks) {
|
|
|
2704
2930
|
confidence: 0.62 + Math.min(0.25, value.count * 0.05)
|
|
2705
2931
|
})
|
|
2706
2932
|
);
|
|
2933
|
+
patternProgress += 1;
|
|
2934
|
+
if (shouldEmitProgress(patternProgress, patternTotal)) {
|
|
2935
|
+
options.onProgress?.({
|
|
2936
|
+
stage: "building_architecture_patterns",
|
|
2937
|
+
repo,
|
|
2938
|
+
current: patternProgress,
|
|
2939
|
+
total: patternTotal,
|
|
2940
|
+
area: sourceArea,
|
|
2941
|
+
patterns: patterns.length
|
|
2942
|
+
});
|
|
2943
|
+
}
|
|
2707
2944
|
}
|
|
2708
2945
|
const testedComponents = components.filter((component) => component.relatedTests.length > 0);
|
|
2709
2946
|
if (testedComponents.length > 0) {
|
|
@@ -3033,8 +3270,24 @@ function detectTestCommands(db, cwd, files = []) {
|
|
|
3033
3270
|
return true;
|
|
3034
3271
|
});
|
|
3035
3272
|
}
|
|
3036
|
-
function refreshTestCommands(db, cwd, repo, files = []) {
|
|
3273
|
+
function refreshTestCommands(db, cwd, repo, files = [], options = {}) {
|
|
3274
|
+
options.onProgress?.({
|
|
3275
|
+
stage: "refreshing_test_commands",
|
|
3276
|
+
repo,
|
|
3277
|
+
phase: "detecting",
|
|
3278
|
+
current: 0,
|
|
3279
|
+
total: files.length,
|
|
3280
|
+
commands: 0
|
|
3281
|
+
});
|
|
3037
3282
|
const commands = detectTestCommands(db, cwd, files);
|
|
3283
|
+
options.onProgress?.({
|
|
3284
|
+
stage: "refreshing_test_commands",
|
|
3285
|
+
repo,
|
|
3286
|
+
phase: "writing",
|
|
3287
|
+
current: 0,
|
|
3288
|
+
total: commands.length,
|
|
3289
|
+
commands: commands.length
|
|
3290
|
+
});
|
|
3038
3291
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3039
3292
|
const transaction = db.transaction(() => {
|
|
3040
3293
|
db.prepare("DELETE FROM test_commands WHERE repo = ?").run(repo);
|
|
@@ -3042,7 +3295,7 @@ function refreshTestCommands(db, cwd, repo, files = []) {
|
|
|
3042
3295
|
`INSERT INTO test_commands (id, repo, file_path, command, reason, confidence, created_at)
|
|
3043
3296
|
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
3044
3297
|
);
|
|
3045
|
-
for (const command of commands) {
|
|
3298
|
+
for (const [index, command] of commands.entries()) {
|
|
3046
3299
|
insert.run(
|
|
3047
3300
|
commandId(repo, command),
|
|
3048
3301
|
repo,
|
|
@@ -3052,6 +3305,17 @@ function refreshTestCommands(db, cwd, repo, files = []) {
|
|
|
3052
3305
|
command.confidence,
|
|
3053
3306
|
now
|
|
3054
3307
|
);
|
|
3308
|
+
const current = index + 1;
|
|
3309
|
+
if (current === 1 || current === commands.length || current % 250 === 0) {
|
|
3310
|
+
options.onProgress?.({
|
|
3311
|
+
stage: "refreshing_test_commands",
|
|
3312
|
+
repo,
|
|
3313
|
+
phase: "writing",
|
|
3314
|
+
current,
|
|
3315
|
+
total: commands.length,
|
|
3316
|
+
commands: commands.length
|
|
3317
|
+
});
|
|
3318
|
+
}
|
|
3055
3319
|
}
|
|
3056
3320
|
});
|
|
3057
3321
|
transaction();
|
|
@@ -3090,7 +3354,9 @@ function indexCodebase(db, options) {
|
|
|
3090
3354
|
chunks: fileChunks.length
|
|
3091
3355
|
});
|
|
3092
3356
|
}
|
|
3093
|
-
const architecture = buildArchitectureIndex(options.repo, discovery.files, chunks
|
|
3357
|
+
const architecture = buildArchitectureIndex(options.repo, discovery.files, chunks, {
|
|
3358
|
+
onProgress: options.onProgress
|
|
3359
|
+
});
|
|
3094
3360
|
options.onProgress?.({
|
|
3095
3361
|
stage: "indexed_architecture",
|
|
3096
3362
|
repo: options.repo,
|
|
@@ -3105,9 +3371,10 @@ function indexCodebase(db, options) {
|
|
|
3105
3371
|
chunks,
|
|
3106
3372
|
discovery.skippedFiles,
|
|
3107
3373
|
options.cwd,
|
|
3108
|
-
architecture
|
|
3374
|
+
architecture,
|
|
3375
|
+
{ onProgress: options.onProgress }
|
|
3109
3376
|
);
|
|
3110
|
-
refreshTestCommands(db, options.cwd, options.repo);
|
|
3377
|
+
refreshTestCommands(db, options.cwd, options.repo, [], { onProgress: options.onProgress });
|
|
3111
3378
|
options.onProgress?.({
|
|
3112
3379
|
stage: "completed_code_index",
|
|
3113
3380
|
repo: options.repo,
|
|
@@ -7929,10 +8196,67 @@ function parseHeartbeat(value) {
|
|
|
7929
8196
|
repoIndex: typeof candidate.repoIndex === "number" ? candidate.repoIndex : void 0,
|
|
7930
8197
|
repoTotal: typeof candidate.repoTotal === "number" ? candidate.repoTotal : void 0,
|
|
7931
8198
|
phase: candidate.phase,
|
|
8199
|
+
timeline: parseTimeline(candidate.timeline),
|
|
7932
8200
|
startedAt: candidate.startedAt,
|
|
7933
8201
|
updatedAt: candidate.updatedAt
|
|
7934
8202
|
};
|
|
7935
8203
|
}
|
|
8204
|
+
function parseTimelineStatus(value) {
|
|
8205
|
+
if (value === "active" || value === "done" || value === "skipped" || value === "warn" || value === "fail" || value === "wait") {
|
|
8206
|
+
return value;
|
|
8207
|
+
}
|
|
8208
|
+
return void 0;
|
|
8209
|
+
}
|
|
8210
|
+
function parseTimelineNumber(value) {
|
|
8211
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8212
|
+
}
|
|
8213
|
+
function parseTimelineStep(value) {
|
|
8214
|
+
if (!value || typeof value !== "object") return void 0;
|
|
8215
|
+
const candidate = value;
|
|
8216
|
+
const status = parseTimelineStatus(candidate.status);
|
|
8217
|
+
if (typeof candidate.id !== "string" || typeof candidate.label !== "string" || !status || typeof candidate.startedAt !== "string" || typeof candidate.updatedAt !== "string") {
|
|
8218
|
+
return void 0;
|
|
8219
|
+
}
|
|
8220
|
+
return {
|
|
8221
|
+
id: candidate.id,
|
|
8222
|
+
label: candidate.label,
|
|
8223
|
+
status,
|
|
8224
|
+
startedAt: candidate.startedAt,
|
|
8225
|
+
updatedAt: candidate.updatedAt,
|
|
8226
|
+
completedAt: typeof candidate.completedAt === "string" ? candidate.completedAt : void 0,
|
|
8227
|
+
durationMs: parseTimelineNumber(candidate.durationMs),
|
|
8228
|
+
current: parseTimelineNumber(candidate.current),
|
|
8229
|
+
total: parseTimelineNumber(candidate.total),
|
|
8230
|
+
detail: typeof candidate.detail === "string" ? candidate.detail : void 0
|
|
8231
|
+
};
|
|
8232
|
+
}
|
|
8233
|
+
function parseTimelineRepoSummary(value) {
|
|
8234
|
+
if (!value || typeof value !== "object") return void 0;
|
|
8235
|
+
const candidate = value;
|
|
8236
|
+
const status = parseTimelineStatus(candidate.status);
|
|
8237
|
+
if (typeof candidate.repo !== "string" || !status) return void 0;
|
|
8238
|
+
return {
|
|
8239
|
+
repo: candidate.repo,
|
|
8240
|
+
status,
|
|
8241
|
+
durationMs: parseTimelineNumber(candidate.durationMs) ?? 0,
|
|
8242
|
+
detail: typeof candidate.detail === "string" ? candidate.detail : void 0
|
|
8243
|
+
};
|
|
8244
|
+
}
|
|
8245
|
+
function parseTimeline(value) {
|
|
8246
|
+
if (!value || typeof value !== "object") return void 0;
|
|
8247
|
+
const candidate = value;
|
|
8248
|
+
if (!Array.isArray(candidate.steps) || !Array.isArray(candidate.recentRepos)) return void 0;
|
|
8249
|
+
const steps = candidate.steps.map(parseTimelineStep).filter((step) => step !== void 0);
|
|
8250
|
+
const recentRepos = candidate.recentRepos.map(parseTimelineRepoSummary).filter((repo) => repo !== void 0);
|
|
8251
|
+
return {
|
|
8252
|
+
repo: typeof candidate.repo === "string" ? candidate.repo : void 0,
|
|
8253
|
+
repoIndex: parseTimelineNumber(candidate.repoIndex),
|
|
8254
|
+
repoTotal: parseTimelineNumber(candidate.repoTotal),
|
|
8255
|
+
activeStepId: typeof candidate.activeStepId === "string" ? candidate.activeStepId : void 0,
|
|
8256
|
+
steps,
|
|
8257
|
+
recentRepos
|
|
8258
|
+
};
|
|
8259
|
+
}
|
|
7936
8260
|
function writeOrgHeartbeat(heartbeat, baseDir) {
|
|
7937
8261
|
atomicWriteJson2(orgHeartbeatPath(heartbeat.org, baseDir), heartbeat);
|
|
7938
8262
|
}
|
|
@@ -8194,7 +8518,7 @@ function isApiConsumerText(text) {
|
|
|
8194
8518
|
function evidenceJson(evidence) {
|
|
8195
8519
|
return JSON.stringify(evidence);
|
|
8196
8520
|
}
|
|
8197
|
-
function
|
|
8521
|
+
function shouldEmitProgress2(current, total, interval = 100) {
|
|
8198
8522
|
return current === 1 || current === total || current % interval === 0;
|
|
8199
8523
|
}
|
|
8200
8524
|
function resolveOptions(baseDirOrOptions) {
|
|
@@ -8300,7 +8624,7 @@ function rebuildOrgGraph(db, config, baseDirOrOptions) {
|
|
|
8300
8624
|
});
|
|
8301
8625
|
break;
|
|
8302
8626
|
}
|
|
8303
|
-
if (
|
|
8627
|
+
if (shouldEmitProgress2(index + 1, imports.length)) {
|
|
8304
8628
|
options.onProgress?.({
|
|
8305
8629
|
stage: "building_import_edges",
|
|
8306
8630
|
org: config.org,
|
|
@@ -8341,7 +8665,7 @@ function rebuildOrgGraph(db, config, baseDirOrOptions) {
|
|
|
8341
8665
|
bucket.push(apiContract);
|
|
8342
8666
|
contractsByToken.set(sanitizedContract, bucket);
|
|
8343
8667
|
}
|
|
8344
|
-
if (
|
|
8668
|
+
if (shouldEmitProgress2(index + 1, providerChunks.length)) {
|
|
8345
8669
|
options.onProgress?.({
|
|
8346
8670
|
stage: "extracting_api_contracts",
|
|
8347
8671
|
org: config.org,
|
|
@@ -8401,7 +8725,7 @@ function rebuildOrgGraph(db, config, baseDirOrOptions) {
|
|
|
8401
8725
|
});
|
|
8402
8726
|
}
|
|
8403
8727
|
}
|
|
8404
|
-
if (
|
|
8728
|
+
if (shouldEmitProgress2(index + 1, consumerChunks.length)) {
|
|
8405
8729
|
options.onProgress?.({
|
|
8406
8730
|
stage: "matching_api_consumers",
|
|
8407
8731
|
org: config.org,
|