@cstart/coldstart 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -0
- package/dist/cache/disk-cache.d.ts +14 -0
- package/dist/cache/disk-cache.d.ts.map +1 -0
- package/dist/cache/disk-cache.js +371 -0
- package/dist/cache/disk-cache.js.map +1 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +206 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +111 -0
- package/dist/constants.js.map +1 -0
- package/dist/daemon-lock.d.ts +63 -0
- package/dist/daemon-lock.d.ts.map +1 -0
- package/dist/daemon-lock.js +218 -0
- package/dist/daemon-lock.js.map +1 -0
- package/dist/daemon-log.d.ts +26 -0
- package/dist/daemon-log.d.ts.map +1 -0
- package/dist/daemon-log.js +110 -0
- package/dist/daemon-log.js.map +1 -0
- package/dist/index-manager.d.ts +103 -0
- package/dist/index-manager.d.ts.map +1 -0
- package/dist/index-manager.js +361 -0
- package/dist/index-manager.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +724 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/content-tokens.d.ts +74 -0
- package/dist/indexer/content-tokens.d.ts.map +1 -0
- package/dist/indexer/content-tokens.js +406 -0
- package/dist/indexer/content-tokens.js.map +1 -0
- package/dist/indexer/cpp-include-roots.d.ts +7 -0
- package/dist/indexer/cpp-include-roots.d.ts.map +1 -0
- package/dist/indexer/cpp-include-roots.js +166 -0
- package/dist/indexer/cpp-include-roots.js.map +1 -0
- package/dist/indexer/csharp-synthetic.d.ts +9 -0
- package/dist/indexer/csharp-synthetic.d.ts.map +1 -0
- package/dist/indexer/csharp-synthetic.js +51 -0
- package/dist/indexer/csharp-synthetic.js.map +1 -0
- package/dist/indexer/django-synthetic.d.ts +12 -0
- package/dist/indexer/django-synthetic.d.ts.map +1 -0
- package/dist/indexer/django-synthetic.js +49 -0
- package/dist/indexer/django-synthetic.js.map +1 -0
- package/dist/indexer/extractors/angularjs.d.ts +16 -0
- package/dist/indexer/extractors/angularjs.d.ts.map +1 -0
- package/dist/indexer/extractors/angularjs.js +49 -0
- package/dist/indexer/extractors/angularjs.js.map +1 -0
- package/dist/indexer/extractors/cpp.d.ts +9 -0
- package/dist/indexer/extractors/cpp.d.ts.map +1 -0
- package/dist/indexer/extractors/cpp.js +254 -0
- package/dist/indexer/extractors/cpp.js.map +1 -0
- package/dist/indexer/extractors/csharp.d.ts +19 -0
- package/dist/indexer/extractors/csharp.d.ts.map +1 -0
- package/dist/indexer/extractors/csharp.js +327 -0
- package/dist/indexer/extractors/csharp.js.map +1 -0
- package/dist/indexer/extractors/env.d.ts +9 -0
- package/dist/indexer/extractors/env.d.ts.map +1 -0
- package/dist/indexer/extractors/env.js +43 -0
- package/dist/indexer/extractors/env.js.map +1 -0
- package/dist/indexer/extractors/go.d.ts +9 -0
- package/dist/indexer/extractors/go.d.ts.map +1 -0
- package/dist/indexer/extractors/go.js +227 -0
- package/dist/indexer/extractors/go.js.map +1 -0
- package/dist/indexer/extractors/graphql.d.ts +22 -0
- package/dist/indexer/extractors/graphql.d.ts.map +1 -0
- package/dist/indexer/extractors/graphql.js +88 -0
- package/dist/indexer/extractors/graphql.js.map +1 -0
- package/dist/indexer/extractors/groovy.d.ts +9 -0
- package/dist/indexer/extractors/groovy.d.ts.map +1 -0
- package/dist/indexer/extractors/groovy.js +356 -0
- package/dist/indexer/extractors/groovy.js.map +1 -0
- package/dist/indexer/extractors/java.d.ts +10 -0
- package/dist/indexer/extractors/java.d.ts.map +1 -0
- package/dist/indexer/extractors/java.js +586 -0
- package/dist/indexer/extractors/java.js.map +1 -0
- package/dist/indexer/extractors/kotlin.d.ts +10 -0
- package/dist/indexer/extractors/kotlin.d.ts.map +1 -0
- package/dist/indexer/extractors/kotlin.js +398 -0
- package/dist/indexer/extractors/kotlin.js.map +1 -0
- package/dist/indexer/extractors/node-helpers.d.ts +13 -0
- package/dist/indexer/extractors/node-helpers.d.ts.map +1 -0
- package/dist/indexer/extractors/node-helpers.js +17 -0
- package/dist/indexer/extractors/node-helpers.js.map +1 -0
- package/dist/indexer/extractors/parser-factory.d.ts +4 -0
- package/dist/indexer/extractors/parser-factory.d.ts.map +1 -0
- package/dist/indexer/extractors/parser-factory.js +28 -0
- package/dist/indexer/extractors/parser-factory.js.map +1 -0
- package/dist/indexer/extractors/php.d.ts +17 -0
- package/dist/indexer/extractors/php.d.ts.map +1 -0
- package/dist/indexer/extractors/php.js +363 -0
- package/dist/indexer/extractors/php.js.map +1 -0
- package/dist/indexer/extractors/python.d.ts +14 -0
- package/dist/indexer/extractors/python.d.ts.map +1 -0
- package/dist/indexer/extractors/python.js +449 -0
- package/dist/indexer/extractors/python.js.map +1 -0
- package/dist/indexer/extractors/ruby.d.ts +10 -0
- package/dist/indexer/extractors/ruby.d.ts.map +1 -0
- package/dist/indexer/extractors/ruby.js +996 -0
- package/dist/indexer/extractors/ruby.js.map +1 -0
- package/dist/indexer/extractors/rust.d.ts +9 -0
- package/dist/indexer/extractors/rust.d.ts.map +1 -0
- package/dist/indexer/extractors/rust.js +322 -0
- package/dist/indexer/extractors/rust.js.map +1 -0
- package/dist/indexer/extractors/toml.d.ts +9 -0
- package/dist/indexer/extractors/toml.d.ts.map +1 -0
- package/dist/indexer/extractors/toml.js +84 -0
- package/dist/indexer/extractors/toml.js.map +1 -0
- package/dist/indexer/extractors/xml.d.ts +9 -0
- package/dist/indexer/extractors/xml.d.ts.map +1 -0
- package/dist/indexer/extractors/xml.js +163 -0
- package/dist/indexer/extractors/xml.js.map +1 -0
- package/dist/indexer/extractors/yaml.d.ts +9 -0
- package/dist/indexer/extractors/yaml.d.ts.map +1 -0
- package/dist/indexer/extractors/yaml.js +117 -0
- package/dist/indexer/extractors/yaml.js.map +1 -0
- package/dist/indexer/git.d.ts +19 -0
- package/dist/indexer/git.d.ts.map +1 -0
- package/dist/indexer/git.js +55 -0
- package/dist/indexer/git.js.map +1 -0
- package/dist/indexer/graph.d.ts +7 -0
- package/dist/indexer/graph.d.ts.map +1 -0
- package/dist/indexer/graph.js +20 -0
- package/dist/indexer/graph.js.map +1 -0
- package/dist/indexer/indexed-file.d.ts +15 -0
- package/dist/indexer/indexed-file.d.ts.map +1 -0
- package/dist/indexer/indexed-file.js +50 -0
- package/dist/indexer/indexed-file.js.map +1 -0
- package/dist/indexer/invariants.d.ts +15 -0
- package/dist/indexer/invariants.d.ts.map +1 -0
- package/dist/indexer/invariants.js +96 -0
- package/dist/indexer/invariants.js.map +1 -0
- package/dist/indexer/laravel-synthetic.d.ts +10 -0
- package/dist/indexer/laravel-synthetic.d.ts.map +1 -0
- package/dist/indexer/laravel-synthetic.js +78 -0
- package/dist/indexer/laravel-synthetic.js.map +1 -0
- package/dist/indexer/parser.d.ts +4 -0
- package/dist/indexer/parser.d.ts.map +1 -0
- package/dist/indexer/parser.js +499 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/patch.d.ts +3 -0
- package/dist/indexer/patch.d.ts.map +1 -0
- package/dist/indexer/patch.js +291 -0
- package/dist/indexer/patch.js.map +1 -0
- package/dist/indexer/rails-synthetic.d.ts +11 -0
- package/dist/indexer/rails-synthetic.d.ts.map +1 -0
- package/dist/indexer/rails-synthetic.js +80 -0
- package/dist/indexer/rails-synthetic.js.map +1 -0
- package/dist/indexer/reconcile.d.ts +9 -0
- package/dist/indexer/reconcile.d.ts.map +1 -0
- package/dist/indexer/reconcile.js +96 -0
- package/dist/indexer/reconcile.js.map +1 -0
- package/dist/indexer/resolvers/cpp.d.ts +15 -0
- package/dist/indexer/resolvers/cpp.d.ts.map +1 -0
- package/dist/indexer/resolvers/cpp.js +35 -0
- package/dist/indexer/resolvers/cpp.js.map +1 -0
- package/dist/indexer/resolvers/csharp.d.ts +2 -0
- package/dist/indexer/resolvers/csharp.d.ts.map +1 -0
- package/dist/indexer/resolvers/csharp.js +89 -0
- package/dist/indexer/resolvers/csharp.js.map +1 -0
- package/dist/indexer/resolvers/generic.d.ts +10 -0
- package/dist/indexer/resolvers/generic.d.ts.map +1 -0
- package/dist/indexer/resolvers/generic.js +35 -0
- package/dist/indexer/resolvers/generic.js.map +1 -0
- package/dist/indexer/resolvers/go.d.ts +2 -0
- package/dist/indexer/resolvers/go.d.ts.map +1 -0
- package/dist/indexer/resolvers/go.js +171 -0
- package/dist/indexer/resolvers/go.js.map +1 -0
- package/dist/indexer/resolvers/index.d.ts +26 -0
- package/dist/indexer/resolvers/index.d.ts.map +1 -0
- package/dist/indexer/resolvers/index.js +301 -0
- package/dist/indexer/resolvers/index.js.map +1 -0
- package/dist/indexer/resolvers/java.d.ts +17 -0
- package/dist/indexer/resolvers/java.d.ts.map +1 -0
- package/dist/indexer/resolvers/java.js +104 -0
- package/dist/indexer/resolvers/java.js.map +1 -0
- package/dist/indexer/resolvers/php.d.ts +2 -0
- package/dist/indexer/resolvers/php.d.ts.map +1 -0
- package/dist/indexer/resolvers/php.js +108 -0
- package/dist/indexer/resolvers/php.js.map +1 -0
- package/dist/indexer/resolvers/python.d.ts +17 -0
- package/dist/indexer/resolvers/python.d.ts.map +1 -0
- package/dist/indexer/resolvers/python.js +63 -0
- package/dist/indexer/resolvers/python.js.map +1 -0
- package/dist/indexer/resolvers/ruby.d.ts +13 -0
- package/dist/indexer/resolvers/ruby.d.ts.map +1 -0
- package/dist/indexer/resolvers/ruby.js +199 -0
- package/dist/indexer/resolvers/ruby.js.map +1 -0
- package/dist/indexer/resolvers/rust.d.ts +12 -0
- package/dist/indexer/resolvers/rust.d.ts.map +1 -0
- package/dist/indexer/resolvers/rust.js +61 -0
- package/dist/indexer/resolvers/rust.js.map +1 -0
- package/dist/indexer/resolvers/shared.d.ts +18 -0
- package/dist/indexer/resolvers/shared.d.ts.map +1 -0
- package/dist/indexer/resolvers/shared.js +71 -0
- package/dist/indexer/resolvers/shared.js.map +1 -0
- package/dist/indexer/rust-workspace.d.ts +25 -0
- package/dist/indexer/rust-workspace.d.ts.map +1 -0
- package/dist/indexer/rust-workspace.js +155 -0
- package/dist/indexer/rust-workspace.js.map +1 -0
- package/dist/indexer/symbol-edges.d.ts +19 -0
- package/dist/indexer/symbol-edges.d.ts.map +1 -0
- package/dist/indexer/symbol-edges.js +117 -0
- package/dist/indexer/symbol-edges.js.map +1 -0
- package/dist/indexer/tokenize.d.ts +26 -0
- package/dist/indexer/tokenize.d.ts.map +1 -0
- package/dist/indexer/tokenize.js +200 -0
- package/dist/indexer/tokenize.js.map +1 -0
- package/dist/indexer/ts-parser.d.ts +10 -0
- package/dist/indexer/ts-parser.d.ts.map +1 -0
- package/dist/indexer/ts-parser.js +605 -0
- package/dist/indexer/ts-parser.js.map +1 -0
- package/dist/indexer/walker.d.ts +9 -0
- package/dist/indexer/walker.d.ts.map +1 -0
- package/dist/indexer/walker.js +91 -0
- package/dist/indexer/walker.js.map +1 -0
- package/dist/init.d.ts +111 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +787 -0
- package/dist/init.js.map +1 -0
- package/dist/kb/cli.d.ts +2 -0
- package/dist/kb/cli.d.ts.map +1 -0
- package/dist/kb/cli.js +377 -0
- package/dist/kb/cli.js.map +1 -0
- package/dist/kb/commit.d.ts +6 -0
- package/dist/kb/commit.d.ts.map +1 -0
- package/dist/kb/commit.js +84 -0
- package/dist/kb/commit.js.map +1 -0
- package/dist/kb/fold.d.ts +42 -0
- package/dist/kb/fold.d.ts.map +1 -0
- package/dist/kb/fold.js +285 -0
- package/dist/kb/fold.js.map +1 -0
- package/dist/kb/freshness.d.ts +9 -0
- package/dist/kb/freshness.d.ts.map +1 -0
- package/dist/kb/freshness.js +52 -0
- package/dist/kb/freshness.js.map +1 -0
- package/dist/kb/git.d.ts +4 -0
- package/dist/kb/git.d.ts.map +1 -0
- package/dist/kb/git.js +28 -0
- package/dist/kb/git.js.map +1 -0
- package/dist/kb/ids.d.ts +8 -0
- package/dist/kb/ids.d.ts.map +1 -0
- package/dist/kb/ids.js +42 -0
- package/dist/kb/ids.js.map +1 -0
- package/dist/kb/lint.d.ts +23 -0
- package/dist/kb/lint.d.ts.map +1 -0
- package/dist/kb/lint.js +102 -0
- package/dist/kb/lint.js.map +1 -0
- package/dist/kb/lookup.d.ts +55 -0
- package/dist/kb/lookup.d.ts.map +1 -0
- package/dist/kb/lookup.js +92 -0
- package/dist/kb/lookup.js.map +1 -0
- package/dist/kb/notes-index.d.ts +31 -0
- package/dist/kb/notes-index.d.ts.map +1 -0
- package/dist/kb/notes-index.js +0 -0
- package/dist/kb/notes-index.js.map +1 -0
- package/dist/kb/raw-log.d.ts +34 -0
- package/dist/kb/raw-log.d.ts.map +1 -0
- package/dist/kb/raw-log.js +106 -0
- package/dist/kb/raw-log.js.map +1 -0
- package/dist/kb/render.d.ts +17 -0
- package/dist/kb/render.d.ts.map +1 -0
- package/dist/kb/render.js +101 -0
- package/dist/kb/render.js.map +1 -0
- package/dist/kb/search.d.ts +110 -0
- package/dist/kb/search.d.ts.map +1 -0
- package/dist/kb/search.js +453 -0
- package/dist/kb/search.js.map +1 -0
- package/dist/kb/store.d.ts +35 -0
- package/dist/kb/store.d.ts.map +1 -0
- package/dist/kb/store.js +160 -0
- package/dist/kb/store.js.map +1 -0
- package/dist/kb/types.d.ts +142 -0
- package/dist/kb/types.d.ts.map +1 -0
- package/dist/kb/types.js +13 -0
- package/dist/kb/types.js.map +1 -0
- package/dist/kb/view-template.d.ts +8 -0
- package/dist/kb/view-template.d.ts.map +1 -0
- package/dist/kb/view-template.js +8 -0
- package/dist/kb/view-template.js.map +1 -0
- package/dist/kb/view.d.ts +42 -0
- package/dist/kb/view.d.ts.map +1 -0
- package/dist/kb/view.js +118 -0
- package/dist/kb/view.js.map +1 -0
- package/dist/kb/write.d.ts +72 -0
- package/dist/kb/write.d.ts.map +1 -0
- package/dist/kb/write.js +345 -0
- package/dist/kb/write.js.map +1 -0
- package/dist/keeper-state.d.ts +29 -0
- package/dist/keeper-state.d.ts.map +1 -0
- package/dist/keeper-state.js +89 -0
- package/dist/keeper-state.js.map +1 -0
- package/dist/keeper.d.ts +23 -0
- package/dist/keeper.d.ts.map +1 -0
- package/dist/keeper.js +105 -0
- package/dist/keeper.js.map +1 -0
- package/dist/migrate.d.ts +9 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +102 -0
- package/dist/migrate.js.map +1 -0
- package/dist/restart.d.ts +15 -0
- package/dist/restart.d.ts.map +1 -0
- package/dist/restart.js +48 -0
- package/dist/restart.js.map +1 -0
- package/dist/server/find.d.ts +39 -0
- package/dist/server/find.d.ts.map +1 -0
- package/dist/server/find.js +979 -0
- package/dist/server/find.js.map +1 -0
- package/dist/server/mcp.d.ts +117 -0
- package/dist/server/mcp.d.ts.map +1 -0
- package/dist/server/mcp.js +301 -0
- package/dist/server/mcp.js.map +1 -0
- package/dist/server/searcher.d.ts +14 -0
- package/dist/server/searcher.d.ts.map +1 -0
- package/dist/server/searcher.js +146 -0
- package/dist/server/searcher.js.map +1 -0
- package/dist/server/tools.d.ts +17 -0
- package/dist/server/tools.d.ts.map +1 -0
- package/dist/server/tools.js +875 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/status.d.ts +12 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +157 -0
- package/dist/status.js.map +1 -0
- package/dist/types.d.ts +138 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/watcher.d.ts +11 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +67 -0
- package/dist/watcher.js.map +1 -0
- package/hooks/canonical-find-key.mjs +68 -0
- package/hooks/codex-find-nudge.mjs +15 -0
- package/hooks/codex-find-preguard.mjs +14 -0
- package/hooks/codex-kb-elicit.mjs +329 -0
- package/hooks/codex-kb-recall.mjs +151 -0
- package/hooks/codex-nudge-handler.mjs +370 -0
- package/hooks/codex-preguard-handler.mjs +75 -0
- package/hooks/codex-run-hook.mjs +132 -0
- package/hooks/coldstart-call.mjs +58 -0
- package/hooks/cursor-find-nudge.mjs +15 -0
- package/hooks/cursor-find-preguard.mjs +14 -0
- package/hooks/cursor-input.mjs +72 -0
- package/hooks/cursor-kb-elicit.mjs +335 -0
- package/hooks/cursor-kb-recall.mjs +138 -0
- package/hooks/cursor-nudge-handler.mjs +33 -0
- package/hooks/cursor-preguard-handler.mjs +39 -0
- package/hooks/cursor-run-hook.mjs +129 -0
- package/hooks/find-nudge.mjs +15 -0
- package/hooks/find-preguard.mjs +14 -0
- package/hooks/kb-elicit.mjs +334 -0
- package/hooks/kb-recall.mjs +151 -0
- package/hooks/nudge-handler.mjs +370 -0
- package/hooks/preguard-handler.mjs +75 -0
- package/hooks/run-hook.mjs +132 -0
- package/package.json +69 -0
- package/templates/coldstart.cli.md +60 -0
- package/templates/coldstart.mcp.md +59 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { relative, extname } from 'node:path';
|
|
3
|
+
import { EXTENSION_TO_LANGUAGE, DEFAULT_EXCLUDES } from '../constants.js';
|
|
4
|
+
import { parseFile, buildFileId } from './parser.js';
|
|
5
|
+
import { buildFileDomains, isTestPath } from './tokenize.js';
|
|
6
|
+
import { resolveImportsForFiles, buildPackageIndex } from './resolvers/index.js';
|
|
7
|
+
import { buildSymbolEdges } from './symbol-edges.js';
|
|
8
|
+
import { buildContentTokenPostings } from './content-tokens.js';
|
|
9
|
+
import { baseIndexedFile } from './indexed-file.js';
|
|
10
|
+
import { addRailsSyntheticEdges } from './rails-synthetic.js';
|
|
11
|
+
import { addLaravelSyntheticEdges } from './laravel-synthetic.js';
|
|
12
|
+
import { addCSharpSyntheticEdges } from './csharp-synthetic.js';
|
|
13
|
+
import { addDjangoSyntheticEdges } from './django-synthetic.js';
|
|
14
|
+
export async function patchIndex(index, changedAbsPaths, rootDir) {
|
|
15
|
+
// Current fileIdSet — used for import resolution of patched files
|
|
16
|
+
const fileIdSet = new Set(index.files.keys());
|
|
17
|
+
// Track which file IDs were touched (for importedByCount recomputation)
|
|
18
|
+
const affectedIds = new Set();
|
|
19
|
+
// -------------------------------------------------------------------------
|
|
20
|
+
// Phase 0: Pre-plan — decide delete/update/skip for every file in the batch
|
|
21
|
+
// WITHOUT touching the index yet. This ensures state is only
|
|
22
|
+
// stripped when we know we can successfully replace it.
|
|
23
|
+
// -------------------------------------------------------------------------
|
|
24
|
+
const plans = new Map();
|
|
25
|
+
for (const absPath of changedAbsPaths) {
|
|
26
|
+
const ext = extname(absPath).toLowerCase();
|
|
27
|
+
const lang = EXTENSION_TO_LANGUAGE[ext];
|
|
28
|
+
if (!lang)
|
|
29
|
+
continue;
|
|
30
|
+
const relPath = relative(rootDir, absPath).replace(/\\/g, '/');
|
|
31
|
+
// Mirror the walker's directory rules: it never descends into hidden or
|
|
32
|
+
// excluded dirs, so a patch must not index files from them either. Both
|
|
33
|
+
// batch producers leak such paths otherwise — the watcher (live edit to
|
|
34
|
+
// .claude/settings.json) and reconcile (porcelain lists it as untracked).
|
|
35
|
+
// Hidden FILES at the root (.rubocop.yml) are walked, so only dir
|
|
36
|
+
// segments are filtered.
|
|
37
|
+
const dirSegments = relPath.split('/').slice(0, -1);
|
|
38
|
+
if (dirSegments.some((s) => s.startsWith('.') || DEFAULT_EXCLUDES.has(s)))
|
|
39
|
+
continue;
|
|
40
|
+
const fileId = buildFileId(relPath);
|
|
41
|
+
// Check existence first (covers deletions)
|
|
42
|
+
let liveStat = null;
|
|
43
|
+
try {
|
|
44
|
+
liveStat = await stat(absPath);
|
|
45
|
+
}
|
|
46
|
+
catch { /* deleted */ }
|
|
47
|
+
if (!liveStat) {
|
|
48
|
+
plans.set(fileId, { absPath, fileId, plan: { action: 'delete' } });
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const parsed = await parseFile(absPath, lang, fileId);
|
|
52
|
+
if (!parsed) {
|
|
53
|
+
// Parse failed — skip this file entirely. Index state is preserved.
|
|
54
|
+
plans.set(fileId, { absPath, fileId, plan: { action: 'skip' } });
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// Hash check: if content is identical, this was a false-positive watch event
|
|
58
|
+
const oldFile = index.files.get(fileId);
|
|
59
|
+
if (oldFile && oldFile.hash === parsed.hash) {
|
|
60
|
+
// Refresh the fingerprint anyway: a touch-without-change moved mtime,
|
|
61
|
+
// and a stale stamp would make reconcile/audit re-flag this file forever.
|
|
62
|
+
oldFile.mtimeMs = liveStat.mtimeMs;
|
|
63
|
+
oldFile.sizeBytes = liveStat.size;
|
|
64
|
+
plans.set(fileId, { absPath, fileId, plan: { action: 'skip' } });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
plans.set(fileId, { absPath, fileId, plan: { action: 'update', parsed, lang, relPath } });
|
|
68
|
+
}
|
|
69
|
+
// -------------------------------------------------------------------------
|
|
70
|
+
// Phase 1: Strip old data — only for files planned as 'delete' or 'update'
|
|
71
|
+
// -------------------------------------------------------------------------
|
|
72
|
+
for (const { fileId, plan } of plans.values()) {
|
|
73
|
+
if (plan.action === 'skip')
|
|
74
|
+
continue;
|
|
75
|
+
affectedIds.add(fileId);
|
|
76
|
+
const oldFile = index.files.get(fileId);
|
|
77
|
+
if (!oldFile)
|
|
78
|
+
continue; // new file — nothing old to remove
|
|
79
|
+
// Remove outgoing flat edges (from === fileId)
|
|
80
|
+
index.edges = index.edges.filter(e => e.from !== fileId);
|
|
81
|
+
// Remove fileId from each import target's inEdges
|
|
82
|
+
const oldOutgoing = index.outEdges.get(fileId) ?? [];
|
|
83
|
+
for (const targetId of oldOutgoing) {
|
|
84
|
+
const importers = index.inEdges.get(targetId);
|
|
85
|
+
if (importers) {
|
|
86
|
+
const i = importers.indexOf(fileId);
|
|
87
|
+
if (i !== -1)
|
|
88
|
+
importers.splice(i, 1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
index.outEdges.set(fileId, []);
|
|
92
|
+
// Decrement tokenDocFreq for old file's tokens (skip barrel files)
|
|
93
|
+
if (!oldFile.isBarrel) {
|
|
94
|
+
for (const token of Object.keys(oldFile.domainMap)) {
|
|
95
|
+
const count = index.tokenDocFreq.get(token) ?? 0;
|
|
96
|
+
if (count <= 1)
|
|
97
|
+
index.tokenDocFreq.delete(token);
|
|
98
|
+
else
|
|
99
|
+
index.tokenDocFreq.set(token, count - 1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Remove symbolEdges originating from this file or its symbols
|
|
103
|
+
const prefix = fileId + '#';
|
|
104
|
+
index.symbolEdges = index.symbolEdges.filter(se => se.from !== fileId && !se.from.startsWith(prefix));
|
|
105
|
+
}
|
|
106
|
+
// -------------------------------------------------------------------------
|
|
107
|
+
// Phase 2: Apply deletions — clean up all graph pointers to deleted files
|
|
108
|
+
// -------------------------------------------------------------------------
|
|
109
|
+
for (const { fileId, plan } of plans.values()) {
|
|
110
|
+
if (plan.action !== 'delete')
|
|
111
|
+
continue;
|
|
112
|
+
// Files that imported the deleted file
|
|
113
|
+
const deletedImporters = index.inEdges.get(fileId) ?? [];
|
|
114
|
+
// Remove ALL flat edges pointing to this deleted file (incoming edges)
|
|
115
|
+
index.edges = index.edges.filter(e => e.to !== fileId);
|
|
116
|
+
// Remove symbolEdges pointing INTO the deleted file (other files' calls /
|
|
117
|
+
// extends / re-exports of its symbols). Phase 1 only strips edges FROM
|
|
118
|
+
// changed files; the callers aren't in the change set, and a dangling
|
|
119
|
+
// se.to fails the invariant lint and forces a full rebuild on every
|
|
120
|
+
// delete of a referenced file.
|
|
121
|
+
const deletedPrefix = fileId + '#';
|
|
122
|
+
index.symbolEdges = index.symbolEdges.filter(se => se.to !== fileId && !se.to.startsWith(deletedPrefix));
|
|
123
|
+
// Remove fileId from each importer's outEdges array
|
|
124
|
+
for (const importerId of deletedImporters) {
|
|
125
|
+
const importerOut = index.outEdges.get(importerId);
|
|
126
|
+
if (importerOut) {
|
|
127
|
+
const i = importerOut.indexOf(fileId);
|
|
128
|
+
if (i !== -1)
|
|
129
|
+
importerOut.splice(i, 1);
|
|
130
|
+
}
|
|
131
|
+
affectedIds.add(importerId);
|
|
132
|
+
}
|
|
133
|
+
index.files.delete(fileId);
|
|
134
|
+
index.outEdges.delete(fileId);
|
|
135
|
+
index.inEdges.delete(fileId);
|
|
136
|
+
fileIdSet.delete(fileId);
|
|
137
|
+
}
|
|
138
|
+
// -------------------------------------------------------------------------
|
|
139
|
+
// Phase 3: Apply updates — build new index entries
|
|
140
|
+
// -------------------------------------------------------------------------
|
|
141
|
+
const newFiles = [];
|
|
142
|
+
for (const { absPath, fileId, plan } of plans.values()) {
|
|
143
|
+
if (plan.action !== 'update')
|
|
144
|
+
continue;
|
|
145
|
+
const { parsed, lang, relPath } = plan;
|
|
146
|
+
const oldFile = index.files.get(fileId);
|
|
147
|
+
const newFile = {
|
|
148
|
+
...baseIndexedFile(fileId, absPath, relPath, lang, parsed),
|
|
149
|
+
domainMap: buildFileDomains(relPath, parsed.exports),
|
|
150
|
+
importedByCount: oldFile?.importedByCount ?? 0,
|
|
151
|
+
transitiveImportedByCount: oldFile?.transitiveImportedByCount ?? 0,
|
|
152
|
+
isBarrel: false,
|
|
153
|
+
isTestFile: isTestPath(relPath),
|
|
154
|
+
};
|
|
155
|
+
index.files.set(fileId, newFile);
|
|
156
|
+
fileIdSet.add(fileId);
|
|
157
|
+
if (!index.inEdges.has(fileId))
|
|
158
|
+
index.inEdges.set(fileId, []);
|
|
159
|
+
index.outEdges.set(fileId, []);
|
|
160
|
+
newFiles.push(newFile);
|
|
161
|
+
}
|
|
162
|
+
if (newFiles.length === 0 && affectedIds.size === 0)
|
|
163
|
+
return; // nothing actionable
|
|
164
|
+
// -------------------------------------------------------------------------
|
|
165
|
+
// Phase 4: Resolve imports for updated files, rebuild edges + inEdges
|
|
166
|
+
// -------------------------------------------------------------------------
|
|
167
|
+
if (newFiles.length > 0) {
|
|
168
|
+
// Build the JVM package index from the FULL set (not just newFiles) so a
|
|
169
|
+
// changed Java/Kotlin file resolves against unchanged ones by declared package.
|
|
170
|
+
const pkgById = buildPackageIndex([...index.files.values()]);
|
|
171
|
+
const { edges: newEdges } = await resolveImportsForFiles(newFiles, fileIdSet, rootDir, pkgById);
|
|
172
|
+
for (const edge of newEdges) {
|
|
173
|
+
index.edges.push(edge);
|
|
174
|
+
// outEdges
|
|
175
|
+
const out = index.outEdges.get(edge.from) ?? [];
|
|
176
|
+
if (!out.includes(edge.to))
|
|
177
|
+
out.push(edge.to);
|
|
178
|
+
index.outEdges.set(edge.from, out);
|
|
179
|
+
// inEdges
|
|
180
|
+
if (!index.inEdges.has(edge.to))
|
|
181
|
+
index.inEdges.set(edge.to, []);
|
|
182
|
+
const inn = index.inEdges.get(edge.to);
|
|
183
|
+
if (!inn.includes(edge.from))
|
|
184
|
+
inn.push(edge.from);
|
|
185
|
+
}
|
|
186
|
+
// -----------------------------------------------------------------------
|
|
187
|
+
// Phase 5: Barrel detection + tokenDocFreq + symbolEdges for new files
|
|
188
|
+
// -----------------------------------------------------------------------
|
|
189
|
+
for (const file of newFiles) {
|
|
190
|
+
if (file.language === 'typescript' || file.language === 'javascript') {
|
|
191
|
+
file.isBarrel = ((file.reexportRatio ?? 0) > 0.5 &&
|
|
192
|
+
(index.inEdges.get(file.id)?.length ?? 0) > 1 &&
|
|
193
|
+
file.exports.length > 0);
|
|
194
|
+
if (file.isBarrel) {
|
|
195
|
+
for (const [token, ev] of Object.entries(file.domainMap)) {
|
|
196
|
+
if (ev.filename === 0 && ev.path === 0) {
|
|
197
|
+
delete file.domainMap[token];
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
file.domainMap[token] = { ...ev, symbol: 0 };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (!file.isBarrel) {
|
|
206
|
+
for (const token of Object.keys(file.domainMap)) {
|
|
207
|
+
index.tokenDocFreq.set(token, (index.tokenDocFreq.get(token) ?? 0) + 1);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
for (const edge of buildSymbolEdges([file], index.outEdges, index.files)) {
|
|
211
|
+
index.symbolEdges.push(edge);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// -----------------------------------------------------------------------
|
|
215
|
+
// Phase 5.5: Refresh synthetic (convention) edges. Phase 1 stripped the
|
|
216
|
+
// outgoing edges of every changed file, INCLUDING its synthetic
|
|
217
|
+
// Rails/Django/Laravel/C# convention edges — so without this, editing a
|
|
218
|
+
// convention file deletes its association/view/route edges until the next
|
|
219
|
+
// full rebuild. The synthetic passes are idempotent (each seeds a `seen`
|
|
220
|
+
// set from the existing edges and only adds what's missing), so re-running
|
|
221
|
+
// them over the full file set re-creates exactly the stripped edges with no
|
|
222
|
+
// duplication. Gate on the languages that actually changed so a
|
|
223
|
+
// non-convention edit (e.g. a TS file in a Rails repo) pays nothing.
|
|
224
|
+
const changedLangs = new Set(newFiles.map(f => f.language));
|
|
225
|
+
if (changedLangs.has('ruby') || changedLangs.has('php') ||
|
|
226
|
+
changedLangs.has('csharp') || changedLangs.has('python')) {
|
|
227
|
+
const allFiles = [...index.files.values()];
|
|
228
|
+
const before = index.edges.length;
|
|
229
|
+
if (changedLangs.has('ruby'))
|
|
230
|
+
await addRailsSyntheticEdges(allFiles, index.edges, fileIdSet, rootDir);
|
|
231
|
+
if (changedLangs.has('php'))
|
|
232
|
+
await addLaravelSyntheticEdges(allFiles, index.edges, fileIdSet, rootDir);
|
|
233
|
+
if (changedLangs.has('csharp'))
|
|
234
|
+
await addCSharpSyntheticEdges(allFiles, index.edges, fileIdSet, rootDir);
|
|
235
|
+
if (changedLangs.has('python'))
|
|
236
|
+
await addDjangoSyntheticEdges(allFiles, index.edges, fileIdSet, rootDir);
|
|
237
|
+
// Sync the newly-added synthetic edges into the graph maps + recompute set.
|
|
238
|
+
for (let i = before; i < index.edges.length; i++) {
|
|
239
|
+
const e = index.edges[i];
|
|
240
|
+
const out = index.outEdges.get(e.from) ?? [];
|
|
241
|
+
if (!out.includes(e.to))
|
|
242
|
+
out.push(e.to);
|
|
243
|
+
index.outEdges.set(e.from, out);
|
|
244
|
+
if (!index.inEdges.has(e.to))
|
|
245
|
+
index.inEdges.set(e.to, []);
|
|
246
|
+
const inn = index.inEdges.get(e.to);
|
|
247
|
+
if (!inn.includes(e.from))
|
|
248
|
+
inn.push(e.from);
|
|
249
|
+
affectedIds.add(e.from);
|
|
250
|
+
affectedIds.add(e.to);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// -------------------------------------------------------------------------
|
|
255
|
+
// Phase 6: Recompute importedByCount for affected files + their neighbours
|
|
256
|
+
// -------------------------------------------------------------------------
|
|
257
|
+
const recomputeSet = new Set(affectedIds);
|
|
258
|
+
for (const fileId of affectedIds) {
|
|
259
|
+
for (const id of index.inEdges.get(fileId) ?? [])
|
|
260
|
+
recomputeSet.add(id);
|
|
261
|
+
for (const id of index.outEdges.get(fileId) ?? [])
|
|
262
|
+
recomputeSet.add(id);
|
|
263
|
+
}
|
|
264
|
+
for (const fileId of recomputeSet) {
|
|
265
|
+
const file = index.files.get(fileId);
|
|
266
|
+
if (file)
|
|
267
|
+
file.importedByCount = index.inEdges.get(fileId)?.length ?? 0;
|
|
268
|
+
}
|
|
269
|
+
// -------------------------------------------------------------------------
|
|
270
|
+
// Phase 7: Recompute transitiveImportedByCount (cheap full pass)
|
|
271
|
+
// -------------------------------------------------------------------------
|
|
272
|
+
for (const file of index.files.values()) {
|
|
273
|
+
file.transitiveImportedByCount = file.importedByCount;
|
|
274
|
+
}
|
|
275
|
+
for (const file of index.files.values()) {
|
|
276
|
+
if (!file.isBarrel)
|
|
277
|
+
continue;
|
|
278
|
+
for (const childId of index.outEdges.get(file.id) ?? []) {
|
|
279
|
+
const child = index.files.get(childId);
|
|
280
|
+
if (child)
|
|
281
|
+
child.transitiveImportedByCount += file.importedByCount;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// -------------------------------------------------------------------------
|
|
285
|
+
// Phase 8: Rebuild content-token postings (cheap full pass — df window 2–5
|
|
286
|
+
// means almost any edit can move tokens in or out of the postings)
|
|
287
|
+
// -------------------------------------------------------------------------
|
|
288
|
+
index.contentTokenPostings = buildContentTokenPostings(index.files.values());
|
|
289
|
+
index.indexedAt = Date.now();
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.js","sourceRoot":"","sources":["../../src/indexer/patch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Edge, IndexedFile } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rails synthetic edges:
|
|
4
|
+
* - Constant references (Zeitwerk autoload): emitted per-AST-reference, resolved
|
|
5
|
+
* against the FQCN index built once from app/<category>/{,concerns/}/*.rb.
|
|
6
|
+
* - Controller/mailer ↔ view folder-pairing: pure path-regex matching the Rails
|
|
7
|
+
* convention. No AST, no render-call parsing. Captures relevance neighborhood
|
|
8
|
+
* (controller + all files in its view folder).
|
|
9
|
+
*/
|
|
10
|
+
export declare function addRailsSyntheticEdges(indexedFiles: IndexedFile[], edges: Edge[], fullFileIdSet: Set<string>, rootDir: string): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=rails-synthetic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rails-synthetic.d.ts","sourceRoot":"","sources":["../../src/indexer/rails-synthetic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,WAAW,EAAE,EAC3B,KAAK,EAAE,IAAI,EAAE,EACb,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAyDf"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { buildRailsFqcnIndex, resolveRailsConstantCandidates } from './resolvers/ruby.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rails synthetic edges:
|
|
4
|
+
* - Constant references (Zeitwerk autoload): emitted per-AST-reference, resolved
|
|
5
|
+
* against the FQCN index built once from app/<category>/{,concerns/}/*.rb.
|
|
6
|
+
* - Controller/mailer ↔ view folder-pairing: pure path-regex matching the Rails
|
|
7
|
+
* convention. No AST, no render-call parsing. Captures relevance neighborhood
|
|
8
|
+
* (controller + all files in its view folder).
|
|
9
|
+
*/
|
|
10
|
+
export async function addRailsSyntheticEdges(indexedFiles, edges, fullFileIdSet, rootDir) {
|
|
11
|
+
const rubyFiles = indexedFiles.filter(f => f.language === 'ruby');
|
|
12
|
+
if (rubyFiles.length === 0)
|
|
13
|
+
return;
|
|
14
|
+
let appRoot = null;
|
|
15
|
+
for (const f of rubyFiles) {
|
|
16
|
+
const idx = f.path.lastIndexOf('/app/');
|
|
17
|
+
if (idx >= 0) {
|
|
18
|
+
appRoot = f.path.substring(0, idx);
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (!appRoot)
|
|
23
|
+
return;
|
|
24
|
+
const fqcnIndex = await buildRailsFqcnIndex(appRoot, fullFileIdSet, rootDir);
|
|
25
|
+
const seen = new Set();
|
|
26
|
+
for (const e of edges)
|
|
27
|
+
seen.add(`${e.from}|${e.to}`);
|
|
28
|
+
for (const f of rubyFiles) {
|
|
29
|
+
if (!f.constantReferences?.length)
|
|
30
|
+
continue;
|
|
31
|
+
for (const candidates of f.constantReferences) {
|
|
32
|
+
const hit = resolveRailsConstantCandidates(candidates, fqcnIndex);
|
|
33
|
+
if (!hit || hit.fileId === f.id)
|
|
34
|
+
continue;
|
|
35
|
+
const key = `${f.id}|${hit.fileId}`;
|
|
36
|
+
if (seen.has(key))
|
|
37
|
+
continue;
|
|
38
|
+
seen.add(key);
|
|
39
|
+
edges.push({ from: f.id, to: hit.fileId, type: 'import', specifier: `const:${hit.fqcn}` });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Folder-pairing: controller/mailer ↔ views in convention folder.
|
|
43
|
+
// app/controllers/<dir>/<name>_controller.rb → app/views/<dir>/<name>/*
|
|
44
|
+
// app/mailers/<name>_mailer.rb → app/views/<name>_mailer/*
|
|
45
|
+
const viewsByDir = new Map();
|
|
46
|
+
for (const id of fullFileIdSet) {
|
|
47
|
+
const m = id.match(/^(.*?)app\/views\/(.+)\/[^/]+$/);
|
|
48
|
+
if (!m)
|
|
49
|
+
continue;
|
|
50
|
+
const key = `${m[1]}::${m[2]}`;
|
|
51
|
+
let arr = viewsByDir.get(key);
|
|
52
|
+
if (!arr) {
|
|
53
|
+
arr = [];
|
|
54
|
+
viewsByDir.set(key, arr);
|
|
55
|
+
}
|
|
56
|
+
arr.push(id);
|
|
57
|
+
}
|
|
58
|
+
const folderRules = [
|
|
59
|
+
{ re: /^(.*?)app\/controllers\/(.+)_controller\.rb$/, viewSuffix: '' },
|
|
60
|
+
{ re: /^(.*?)app\/mailers\/(.+)_mailer\.rb$/, viewSuffix: '_mailer' },
|
|
61
|
+
];
|
|
62
|
+
for (const f of indexedFiles) {
|
|
63
|
+
for (const rule of folderRules) {
|
|
64
|
+
const m = f.id.match(rule.re);
|
|
65
|
+
if (!m)
|
|
66
|
+
continue;
|
|
67
|
+
const targets = viewsByDir.get(`${m[1]}::${m[2]}${rule.viewSuffix}`);
|
|
68
|
+
if (!targets)
|
|
69
|
+
continue;
|
|
70
|
+
for (const targetId of targets) {
|
|
71
|
+
const key = `${f.id}|${targetId}`;
|
|
72
|
+
if (seen.has(key))
|
|
73
|
+
continue;
|
|
74
|
+
seen.add(key);
|
|
75
|
+
edges.push({ from: f.id, to: targetId, type: 'import', specifier: 'convention:views' });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=rails-synthetic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rails-synthetic.js","sourceRoot":"","sources":["../../src/indexer/rails-synthetic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CodebaseIndex } from '../types.js';
|
|
2
|
+
export interface ReconcileResult {
|
|
3
|
+
/** Absolute paths — feed straight to patchIndex (it plans delete/update/skip itself). */
|
|
4
|
+
changed: Set<string>;
|
|
5
|
+
/** One line for the keeper log / repair log / status. */
|
|
6
|
+
reason: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function reconcileChanges(index: CodebaseIndex, rootDir: string, excludes?: string[], includes?: string[]): Promise<ReconcileResult | null>;
|
|
9
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/indexer/reconcile.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;CAChB;AAaD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAAM,EAAO,EACvB,QAAQ,GAAE,MAAM,EAAO,GACtB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAkDjC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Startup reconcile — answers "which files changed while no keeper was
|
|
3
|
+
* watching?" so a loaded cache can be PATCHED instead of discarded. This is
|
|
4
|
+
* the freshness mechanism that replaced the deleted cache TTL: validity is
|
|
5
|
+
* version + this reconcile + the keeper's live watcher.
|
|
6
|
+
*
|
|
7
|
+
* Two detectors, both always relevant:
|
|
8
|
+
*
|
|
9
|
+
* stale/deleted — a stat-walk over every indexed file, comparing live
|
|
10
|
+
* [mtimeMs, size] against the fingerprint stamped at parse time. Runs
|
|
11
|
+
* unconditionally (~100-200ms for 16k files): git alone would miss files
|
|
12
|
+
* that were indexed dirty and then reverted (clean tree, stale index),
|
|
13
|
+
* and gitignored-but-indexed files.
|
|
14
|
+
*
|
|
15
|
+
* new files — a stat-walk can't see files the index has never met. git
|
|
16
|
+
* (diff against the stored HEAD + porcelain for untracked) supplies them
|
|
17
|
+
* cheaply; non-git repos or git failure fall back to a directory walk.
|
|
18
|
+
*
|
|
19
|
+
* Known blind spot (accepted): an edit that preserves both mtime and size is
|
|
20
|
+
* invisible to the fingerprint, and a NEW gitignored file in a git repo is
|
|
21
|
+
* invisible to porcelain. The live watcher catches both from spawn onward.
|
|
22
|
+
*
|
|
23
|
+
* Returns null only when even the walk fails — caller does a full rebuild.
|
|
24
|
+
*/
|
|
25
|
+
import { stat } from 'node:fs/promises';
|
|
26
|
+
import { join } from 'node:path';
|
|
27
|
+
import { getGitHead, getGitChangedFiles, getGitDirtyFiles } from './git.js';
|
|
28
|
+
import { walkDirectory } from './walker.js';
|
|
29
|
+
import { DEFAULT_EXCLUDES } from '../constants.js';
|
|
30
|
+
/** Live stat vs stored fingerprint. true = index no longer reflects this file. */
|
|
31
|
+
async function isStale(absPath, mtimeMs, sizeBytes) {
|
|
32
|
+
try {
|
|
33
|
+
const st = await stat(absPath);
|
|
34
|
+
if (mtimeMs === undefined || sizeBytes === undefined)
|
|
35
|
+
return true; // never stamped — re-parse to be safe
|
|
36
|
+
return st.mtimeMs !== mtimeMs || st.size !== sizeBytes;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return true; // gone — patch plans a delete
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export async function reconcileChanges(index, rootDir, excludes = [], includes = []) {
|
|
43
|
+
const changed = new Set();
|
|
44
|
+
// ---- stale/deleted: fingerprint stat-walk over the indexed files ---------
|
|
45
|
+
for (const f of index.files.values()) {
|
|
46
|
+
if (await isStale(f.path, f.mtimeMs, f.sizeBytes))
|
|
47
|
+
changed.add(f.path);
|
|
48
|
+
}
|
|
49
|
+
const staleCount = changed.size;
|
|
50
|
+
// ---- new files: git fast path, directory-walk fallback -------------------
|
|
51
|
+
const indexed = new Set();
|
|
52
|
+
for (const f of index.files.values())
|
|
53
|
+
indexed.add(f.path);
|
|
54
|
+
let newSource;
|
|
55
|
+
const head = await getGitHead(rootDir);
|
|
56
|
+
const committed = head && index.gitHead && head !== index.gitHead
|
|
57
|
+
? await getGitChangedFiles(rootDir, index.gitHead)
|
|
58
|
+
: head ? [] : null;
|
|
59
|
+
const dirty = head ? await getGitDirtyFiles(rootDir) : null;
|
|
60
|
+
if (committed !== null && dirty !== null) {
|
|
61
|
+
newSource = head === index.gitHead ? 'git-status' : 'git-diff+status';
|
|
62
|
+
for (const rel of [...committed, ...dirty]) {
|
|
63
|
+
// The walker never descends into hidden/excluded dirs — porcelain does
|
|
64
|
+
// (.claude/settings.json is a real untracked file). Without this filter
|
|
65
|
+
// every keeper start "discovers" it and pays a no-op patch + re-save.
|
|
66
|
+
const dirSegments = rel.split('/').slice(0, -1);
|
|
67
|
+
if (dirSegments.some((s) => s.startsWith('.') || DEFAULT_EXCLUDES.has(s) || excludes.includes(s)))
|
|
68
|
+
continue;
|
|
69
|
+
const abs = join(rootDir, rel);
|
|
70
|
+
if (indexed.has(abs) || changed.has(abs))
|
|
71
|
+
continue; // known file — stat-walk already judged it
|
|
72
|
+
try {
|
|
73
|
+
await stat(abs);
|
|
74
|
+
changed.add(abs); // exists but never indexed → new (patch filters non-indexable extensions)
|
|
75
|
+
}
|
|
76
|
+
catch { /* listed but gone and never indexed — nothing to do */ }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
newSource = 'fs-walk';
|
|
81
|
+
try {
|
|
82
|
+
const walked = await walkDirectory({ rootDir, excludes, includes });
|
|
83
|
+
for (const wf of walked) {
|
|
84
|
+
if (!indexed.has(wf.absolutePath))
|
|
85
|
+
changed.add(wf.absolutePath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Can't even enumerate the repo — no safe patch set exists.
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const reason = `reconcile(${newSource}): ${staleCount} stale/deleted + ${changed.size - staleCount} new`;
|
|
94
|
+
return { changed, reason };
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=reconcile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/indexer/reconcile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C++ resolver: handles both #include "path/to/file.h" and #include <path/to/file.h>.
|
|
3
|
+
*
|
|
4
|
+
* The extractor passes both quoted and angle-bracket includes (after filtering
|
|
5
|
+
* out stdlib/third-party), since modern CMake projects use angle-brackets for
|
|
6
|
+
* their own internal headers when they set up include roots via
|
|
7
|
+
* include_directories() / target_include_directories().
|
|
8
|
+
*
|
|
9
|
+
* Resolution order:
|
|
10
|
+
* 1. Relative to the including file's directory (for quoted includes)
|
|
11
|
+
* 2. For each include root discovered from CMakeLists.txt (walk-up from file)
|
|
12
|
+
* 3. Fallback to rootDir-relative
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveCpp(specifier: string, fromFile: string, fileIdSet: Set<string>, rootDir: string, _aliasMap: Map<string, string[]>): Promise<string | null>;
|
|
15
|
+
//# sourceMappingURL=cpp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpp.d.ts","sourceRoot":"","sources":["../../../src/indexer/resolvers/cpp.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAC/B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiBxB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { dirname, join, resolve } from 'node:path';
|
|
2
|
+
import { tryResolveBase } from './shared.js';
|
|
3
|
+
import { getCppIncludeRoots } from '../cpp-include-roots.js';
|
|
4
|
+
/**
|
|
5
|
+
* C++ resolver: handles both #include "path/to/file.h" and #include <path/to/file.h>.
|
|
6
|
+
*
|
|
7
|
+
* The extractor passes both quoted and angle-bracket includes (after filtering
|
|
8
|
+
* out stdlib/third-party), since modern CMake projects use angle-brackets for
|
|
9
|
+
* their own internal headers when they set up include roots via
|
|
10
|
+
* include_directories() / target_include_directories().
|
|
11
|
+
*
|
|
12
|
+
* Resolution order:
|
|
13
|
+
* 1. Relative to the including file's directory (for quoted includes)
|
|
14
|
+
* 2. For each include root discovered from CMakeLists.txt (walk-up from file)
|
|
15
|
+
* 3. Fallback to rootDir-relative
|
|
16
|
+
*/
|
|
17
|
+
export async function resolveCpp(specifier, fromFile, fileIdSet, rootDir, _aliasMap) {
|
|
18
|
+
// Try relative to the including file first
|
|
19
|
+
const fromDir = resolve(dirname(fromFile), specifier);
|
|
20
|
+
const result = tryResolveBase(fromDir, fileIdSet, rootDir);
|
|
21
|
+
if (result)
|
|
22
|
+
return result;
|
|
23
|
+
// Try each include root from CMakeLists.txt
|
|
24
|
+
const includeRoots = await getCppIncludeRoots(dirname(fromFile), rootDir);
|
|
25
|
+
for (const root of includeRoots) {
|
|
26
|
+
const candidate = join(root, specifier);
|
|
27
|
+
const resolved = tryResolveBase(candidate, fileIdSet, rootDir);
|
|
28
|
+
if (resolved)
|
|
29
|
+
return resolved;
|
|
30
|
+
}
|
|
31
|
+
// Fall back to rootDir-relative (project-wide include root)
|
|
32
|
+
const fromRoot = join(rootDir, specifier);
|
|
33
|
+
return tryResolveBase(fromRoot, fileIdSet, rootDir);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=cpp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpp.js","sourceRoot":"","sources":["../../../src/indexer/resolvers/cpp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,SAAiB,EACjB,QAAgB,EAChB,SAAsB,EACtB,OAAe,EACf,SAAgC;IAEhC,2CAA2C;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3D,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,4CAA4C;IAC5C,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1E,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/D,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;IAChC,CAAC;IAED,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC1C,OAAO,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csharp.d.ts","sourceRoot":"","sources":["../../../src/indexer/resolvers/csharp.ts"],"names":[],"mappings":"AA4EA,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAChC,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuBxB"}
|