@spikedpunch/mast 0.1.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.
Files changed (257) hide show
  1. package/LICENSE +21 -0
  2. package/MAST_SPEC.md +2926 -0
  3. package/README.md +842 -0
  4. package/assets/skill.md +45 -0
  5. package/dist/ast/extract.d.ts +65 -0
  6. package/dist/ast/extract.d.ts.map +1 -0
  7. package/dist/ast/extract.js +147 -0
  8. package/dist/ast/extract.js.map +1 -0
  9. package/dist/ast/extractor.d.ts +85 -0
  10. package/dist/ast/extractor.d.ts.map +1 -0
  11. package/dist/ast/extractor.js +2 -0
  12. package/dist/ast/extractor.js.map +1 -0
  13. package/dist/ast/extractors/markdown.d.ts +40 -0
  14. package/dist/ast/extractors/markdown.d.ts.map +1 -0
  15. package/dist/ast/extractors/markdown.js +175 -0
  16. package/dist/ast/extractors/markdown.js.map +1 -0
  17. package/dist/ast/extractors/typescript.d.ts +179 -0
  18. package/dist/ast/extractors/typescript.d.ts.map +1 -0
  19. package/dist/ast/extractors/typescript.js +1439 -0
  20. package/dist/ast/extractors/typescript.js.map +1 -0
  21. package/dist/ast/parser.d.ts +5 -0
  22. package/dist/ast/parser.d.ts.map +1 -0
  23. package/dist/ast/parser.js +21 -0
  24. package/dist/ast/parser.js.map +1 -0
  25. package/dist/ast/types.d.ts +586 -0
  26. package/dist/ast/types.d.ts.map +1 -0
  27. package/dist/ast/types.js +3 -0
  28. package/dist/ast/types.js.map +1 -0
  29. package/dist/cli/docs-cmd.d.ts +22 -0
  30. package/dist/cli/docs-cmd.d.ts.map +1 -0
  31. package/dist/cli/docs-cmd.js +100 -0
  32. package/dist/cli/docs-cmd.js.map +1 -0
  33. package/dist/cli/index-cmd.d.ts +72 -0
  34. package/dist/cli/index-cmd.d.ts.map +1 -0
  35. package/dist/cli/index-cmd.js +263 -0
  36. package/dist/cli/index-cmd.js.map +1 -0
  37. package/dist/cli/index.d.ts +3 -0
  38. package/dist/cli/index.d.ts.map +1 -0
  39. package/dist/cli/index.js +4 -0
  40. package/dist/cli/index.js.map +1 -0
  41. package/dist/cli/init.d.ts +14 -0
  42. package/dist/cli/init.d.ts.map +1 -0
  43. package/dist/cli/init.js +64 -0
  44. package/dist/cli/init.js.map +1 -0
  45. package/dist/cli/install-hooks.d.ts +3 -0
  46. package/dist/cli/install-hooks.d.ts.map +1 -0
  47. package/dist/cli/install-hooks.js +34 -0
  48. package/dist/cli/install-hooks.js.map +1 -0
  49. package/dist/cli/metrics-cmd.d.ts +3 -0
  50. package/dist/cli/metrics-cmd.d.ts.map +1 -0
  51. package/dist/cli/metrics-cmd.js +164 -0
  52. package/dist/cli/metrics-cmd.js.map +1 -0
  53. package/dist/cli/program.d.ts +14 -0
  54. package/dist/cli/program.d.ts.map +1 -0
  55. package/dist/cli/program.js +44 -0
  56. package/dist/cli/program.js.map +1 -0
  57. package/dist/cli/query.d.ts +46 -0
  58. package/dist/cli/query.d.ts.map +1 -0
  59. package/dist/cli/query.js +153 -0
  60. package/dist/cli/query.js.map +1 -0
  61. package/dist/cli/search-cmd.d.ts +33 -0
  62. package/dist/cli/search-cmd.d.ts.map +1 -0
  63. package/dist/cli/search-cmd.js +114 -0
  64. package/dist/cli/search-cmd.js.map +1 -0
  65. package/dist/cli/serve.d.ts +3 -0
  66. package/dist/cli/serve.d.ts.map +1 -0
  67. package/dist/cli/serve.js +19 -0
  68. package/dist/cli/serve.js.map +1 -0
  69. package/dist/cli/skill-install.d.ts +39 -0
  70. package/dist/cli/skill-install.d.ts.map +1 -0
  71. package/dist/cli/skill-install.js +57 -0
  72. package/dist/cli/skill-install.js.map +1 -0
  73. package/dist/cli/status.d.ts +35 -0
  74. package/dist/cli/status.d.ts.map +1 -0
  75. package/dist/cli/status.js +117 -0
  76. package/dist/cli/status.js.map +1 -0
  77. package/dist/cli/upgrade-cmd.d.ts +48 -0
  78. package/dist/cli/upgrade-cmd.d.ts.map +1 -0
  79. package/dist/cli/upgrade-cmd.js +129 -0
  80. package/dist/cli/upgrade-cmd.js.map +1 -0
  81. package/dist/cli/version.d.ts +3 -0
  82. package/dist/cli/version.d.ts.map +1 -0
  83. package/dist/cli/version.js +19 -0
  84. package/dist/cli/version.js.map +1 -0
  85. package/dist/env.d.ts +17 -0
  86. package/dist/env.d.ts.map +1 -0
  87. package/dist/env.js +17 -0
  88. package/dist/env.js.map +1 -0
  89. package/dist/graph/checker-resolver.d.ts +156 -0
  90. package/dist/graph/checker-resolver.d.ts.map +1 -0
  91. package/dist/graph/checker-resolver.js +458 -0
  92. package/dist/graph/checker-resolver.js.map +1 -0
  93. package/dist/graph/db.d.ts +318 -0
  94. package/dist/graph/db.d.ts.map +1 -0
  95. package/dist/graph/db.js +266 -0
  96. package/dist/graph/db.js.map +1 -0
  97. package/dist/graph/index.d.ts +4 -0
  98. package/dist/graph/index.d.ts.map +1 -0
  99. package/dist/graph/index.js +5 -0
  100. package/dist/graph/index.js.map +1 -0
  101. package/dist/graph/local-type-env.d.ts +45 -0
  102. package/dist/graph/local-type-env.d.ts.map +1 -0
  103. package/dist/graph/local-type-env.js +59 -0
  104. package/dist/graph/local-type-env.js.map +1 -0
  105. package/dist/graph/path-range.d.ts +40 -0
  106. package/dist/graph/path-range.d.ts.map +1 -0
  107. package/dist/graph/path-range.js +42 -0
  108. package/dist/graph/path-range.js.map +1 -0
  109. package/dist/graph/populate.d.ts +263 -0
  110. package/dist/graph/populate.d.ts.map +1 -0
  111. package/dist/graph/populate.js +984 -0
  112. package/dist/graph/populate.js.map +1 -0
  113. package/dist/graph/queries.d.ts +114 -0
  114. package/dist/graph/queries.d.ts.map +1 -0
  115. package/dist/graph/queries.js +415 -0
  116. package/dist/graph/queries.js.map +1 -0
  117. package/dist/graph/sqliteBatch.d.ts +48 -0
  118. package/dist/graph/sqliteBatch.d.ts.map +1 -0
  119. package/dist/graph/sqliteBatch.js +93 -0
  120. package/dist/graph/sqliteBatch.js.map +1 -0
  121. package/dist/indexer/freshness.d.ts +48 -0
  122. package/dist/indexer/freshness.d.ts.map +1 -0
  123. package/dist/indexer/freshness.js +72 -0
  124. package/dist/indexer/freshness.js.map +1 -0
  125. package/dist/indexer/import-resolver.d.ts +50 -0
  126. package/dist/indexer/import-resolver.d.ts.map +1 -0
  127. package/dist/indexer/import-resolver.js +318 -0
  128. package/dist/indexer/import-resolver.js.map +1 -0
  129. package/dist/indexer/index.d.ts +249 -0
  130. package/dist/indexer/index.d.ts.map +1 -0
  131. package/dist/indexer/index.js +560 -0
  132. package/dist/indexer/index.js.map +1 -0
  133. package/dist/indexer/walker.d.ts +60 -0
  134. package/dist/indexer/walker.d.ts.map +1 -0
  135. package/dist/indexer/walker.js +128 -0
  136. package/dist/indexer/walker.js.map +1 -0
  137. package/dist/indexer/watcher.d.ts +80 -0
  138. package/dist/indexer/watcher.d.ts.map +1 -0
  139. package/dist/indexer/watcher.js +151 -0
  140. package/dist/indexer/watcher.js.map +1 -0
  141. package/dist/mcp/context.d.ts +23 -0
  142. package/dist/mcp/context.d.ts.map +1 -0
  143. package/dist/mcp/context.js +2 -0
  144. package/dist/mcp/context.js.map +1 -0
  145. package/dist/mcp/register-tools.d.ts +21 -0
  146. package/dist/mcp/register-tools.d.ts.map +1 -0
  147. package/dist/mcp/register-tools.js +42 -0
  148. package/dist/mcp/register-tools.js.map +1 -0
  149. package/dist/mcp/server.d.ts +58 -0
  150. package/dist/mcp/server.d.ts.map +1 -0
  151. package/dist/mcp/server.js +177 -0
  152. package/dist/mcp/server.js.map +1 -0
  153. package/dist/mcp/staleness.d.ts +72 -0
  154. package/dist/mcp/staleness.d.ts.map +1 -0
  155. package/dist/mcp/staleness.js +213 -0
  156. package/dist/mcp/staleness.js.map +1 -0
  157. package/dist/mcp/startup.d.ts +40 -0
  158. package/dist/mcp/startup.d.ts.map +1 -0
  159. package/dist/mcp/startup.js +114 -0
  160. package/dist/mcp/startup.js.map +1 -0
  161. package/dist/mcp/tools/_helpers.d.ts +26 -0
  162. package/dist/mcp/tools/_helpers.d.ts.map +1 -0
  163. package/dist/mcp/tools/_helpers.js +54 -0
  164. package/dist/mcp/tools/_helpers.js.map +1 -0
  165. package/dist/mcp/tools/callers.d.ts +4 -0
  166. package/dist/mcp/tools/callers.d.ts.map +1 -0
  167. package/dist/mcp/tools/callers.js +112 -0
  168. package/dist/mcp/tools/callers.js.map +1 -0
  169. package/dist/mcp/tools/dependencies.d.ts +4 -0
  170. package/dist/mcp/tools/dependencies.d.ts.map +1 -0
  171. package/dist/mcp/tools/dependencies.js +36 -0
  172. package/dist/mcp/tools/dependencies.js.map +1 -0
  173. package/dist/mcp/tools/efficiency.d.ts +4 -0
  174. package/dist/mcp/tools/efficiency.d.ts.map +1 -0
  175. package/dist/mcp/tools/efficiency.js +39 -0
  176. package/dist/mcp/tools/efficiency.js.map +1 -0
  177. package/dist/mcp/tools/exports.d.ts +4 -0
  178. package/dist/mcp/tools/exports.d.ts.map +1 -0
  179. package/dist/mcp/tools/exports.js +56 -0
  180. package/dist/mcp/tools/exports.js.map +1 -0
  181. package/dist/mcp/tools/implementors.d.ts +4 -0
  182. package/dist/mcp/tools/implementors.d.ts.map +1 -0
  183. package/dist/mcp/tools/implementors.js +47 -0
  184. package/dist/mcp/tools/implementors.js.map +1 -0
  185. package/dist/mcp/tools/project-skeleton.d.ts +4 -0
  186. package/dist/mcp/tools/project-skeleton.d.ts.map +1 -0
  187. package/dist/mcp/tools/project-skeleton.js +61 -0
  188. package/dist/mcp/tools/project-skeleton.js.map +1 -0
  189. package/dist/mcp/tools/reindex.d.ts +14 -0
  190. package/dist/mcp/tools/reindex.d.ts.map +1 -0
  191. package/dist/mcp/tools/reindex.js +32 -0
  192. package/dist/mcp/tools/reindex.js.map +1 -0
  193. package/dist/mcp/tools/rename-impact.d.ts +4 -0
  194. package/dist/mcp/tools/rename-impact.d.ts.map +1 -0
  195. package/dist/mcp/tools/rename-impact.js +124 -0
  196. package/dist/mcp/tools/rename-impact.js.map +1 -0
  197. package/dist/mcp/tools/search.d.ts +4 -0
  198. package/dist/mcp/tools/search.d.ts.map +1 -0
  199. package/dist/mcp/tools/search.js +69 -0
  200. package/dist/mcp/tools/search.js.map +1 -0
  201. package/dist/mcp/tools/signature.d.ts +4 -0
  202. package/dist/mcp/tools/signature.d.ts.map +1 -0
  203. package/dist/mcp/tools/signature.js +127 -0
  204. package/dist/mcp/tools/signature.js.map +1 -0
  205. package/dist/mcp/tools/status.d.ts +4 -0
  206. package/dist/mcp/tools/status.d.ts.map +1 -0
  207. package/dist/mcp/tools/status.js +30 -0
  208. package/dist/mcp/tools/status.js.map +1 -0
  209. package/dist/search/declex.d.ts +109 -0
  210. package/dist/search/declex.d.ts.map +1 -0
  211. package/dist/search/declex.js +242 -0
  212. package/dist/search/declex.js.map +1 -0
  213. package/dist/search/fts.d.ts +77 -0
  214. package/dist/search/fts.d.ts.map +1 -0
  215. package/dist/search/fts.js +223 -0
  216. package/dist/search/fts.js.map +1 -0
  217. package/dist/search/fused.d.ts +110 -0
  218. package/dist/search/fused.d.ts.map +1 -0
  219. package/dist/search/fused.js +323 -0
  220. package/dist/search/fused.js.map +1 -0
  221. package/dist/search/potential-matches.d.ts +88 -0
  222. package/dist/search/potential-matches.d.ts.map +1 -0
  223. package/dist/search/potential-matches.js +83 -0
  224. package/dist/search/potential-matches.js.map +1 -0
  225. package/dist/search/scope.d.ts +66 -0
  226. package/dist/search/scope.d.ts.map +1 -0
  227. package/dist/search/scope.js +71 -0
  228. package/dist/search/scope.js.map +1 -0
  229. package/dist/store/config.d.ts +57 -0
  230. package/dist/store/config.d.ts.map +1 -0
  231. package/dist/store/config.js +208 -0
  232. package/dist/store/config.js.map +1 -0
  233. package/dist/store/lock.d.ts +101 -0
  234. package/dist/store/lock.d.ts.map +1 -0
  235. package/dist/store/lock.js +182 -0
  236. package/dist/store/lock.js.map +1 -0
  237. package/dist/store/lockMetrics.d.ts +52 -0
  238. package/dist/store/lockMetrics.d.ts.map +1 -0
  239. package/dist/store/lockMetrics.js +29 -0
  240. package/dist/store/lockMetrics.js.map +1 -0
  241. package/dist/store/sqliteChunkStore.d.ts +44 -0
  242. package/dist/store/sqliteChunkStore.d.ts.map +1 -0
  243. package/dist/store/sqliteChunkStore.js +135 -0
  244. package/dist/store/sqliteChunkStore.js.map +1 -0
  245. package/dist/telemetry/lockMetricsSummary.d.ts +42 -0
  246. package/dist/telemetry/lockMetricsSummary.d.ts.map +1 -0
  247. package/dist/telemetry/lockMetricsSummary.js +139 -0
  248. package/dist/telemetry/lockMetricsSummary.js.map +1 -0
  249. package/dist/telemetry/metrics.d.ts +140 -0
  250. package/dist/telemetry/metrics.d.ts.map +1 -0
  251. package/dist/telemetry/metrics.js +312 -0
  252. package/dist/telemetry/metrics.js.map +1 -0
  253. package/dist/telemetry/tokenizer.d.ts +125 -0
  254. package/dist/telemetry/tokenizer.d.ts.map +1 -0
  255. package/dist/telemetry/tokenizer.js +174 -0
  256. package/dist/telemetry/tokenizer.js.map +1 -0
  257. package/package.json +81 -0
@@ -0,0 +1,156 @@
1
+ import ts from 'typescript';
2
+ import type { Db } from './db.js';
3
+ import type { ChunkStore } from '../store/sqliteChunkStore.js';
4
+ import type { ResolvedConfig } from '../store/config.js';
5
+ /** One tsconfig project the checker pass can build a `ts.Program` for. */
6
+ export interface TsProjectDescriptor {
7
+ /** Directory containing tsconfig.json, relative to the project root (POSIX separators). */
8
+ readonly configDir: string;
9
+ /** Absolute paths TypeScript itself resolved via this tsconfig's "include"/"files". */
10
+ readonly fileNames: readonly string[];
11
+ readonly compilerOptions: ts.CompilerOptions;
12
+ }
13
+ /** A tsconfig.json that was found but is not a standalone checkable project. */
14
+ export interface TsProjectSkip {
15
+ readonly configDir: string;
16
+ readonly reason: string;
17
+ }
18
+ export interface TsProjectDiscoveryResult {
19
+ readonly projects: readonly TsProjectDescriptor[];
20
+ readonly skipped: readonly TsProjectSkip[];
21
+ }
22
+ /**
23
+ * Enumerate every tsconfig project under `projectRoot`.
24
+ *
25
+ * A tsconfig.json is a real, checkable project when `ts.parseJsonConfigFileContent`
26
+ * resolves at least one source file for it. A base config meant to be
27
+ * `extends`-ed (e.g. `tsconfig.base.json`) declares no "include"/"files" of
28
+ * its own and resolves zero files — skipped with reason `no_include_base_config`.
29
+ * A config that fails to parse is skipped with the parser's own error text.
30
+ * This is a generic, project-shape-agnostic rule (unlike the Stage 1.1 spike's
31
+ * hardcoded 25-project list for the kluster monorepo specifically) so it works
32
+ * for any project `mast index --checker` runs against, monorepo or single-app.
33
+ */
34
+ export declare function discoverTsConfigProjects(projectRoot: string): TsProjectDiscoveryResult;
35
+ /** One call-site candidate to classify against a loaded project's program. */
36
+ export interface ClassifyInput {
37
+ /** File containing the candidate call site, relative to the project root. */
38
+ readonly relFilePath: string;
39
+ /** Bare (post-`.`) name being searched for — `ClassName.method` → `method`. */
40
+ readonly bareName: string;
41
+ /** Padded search window: the potential match's chunk start/end lines. */
42
+ readonly startLine: number;
43
+ readonly endLine: number;
44
+ /** The queried symbol's own declaration site, for the resolved-declaration comparison. */
45
+ readonly queriedFilePath: string;
46
+ readonly queriedLine: number;
47
+ }
48
+ export type CallSiteClassification = {
49
+ readonly kind: 'resolves_to_queried';
50
+ readonly callLine: number;
51
+ readonly context: string;
52
+ } | {
53
+ readonly kind: 'resolves_to_different';
54
+ } | {
55
+ readonly kind: 'non_call_site';
56
+ } | {
57
+ readonly kind: 'unresolved';
58
+ };
59
+ /**
60
+ * A loaded TypeScript project — one `ts.Program` + `ts.TypeChecker`.
61
+ *
62
+ * Callers MUST call `dispose()` before loading the next project; the checker
63
+ * pass holds exactly one handle at a time (see module doc — the RSS gate).
64
+ */
65
+ export interface TsProjectHandle {
66
+ classify(input: ClassifyInput): CallSiteClassification;
67
+ /** Release the underlying program/checker. Idempotent; `classify()` after `dispose()` throws. */
68
+ dispose(): void;
69
+ }
70
+ /**
71
+ * Abstraction over "hold a TypeScript program for one project and classify
72
+ * call sites against it." The real implementation wraps `ts.createProgram` +
73
+ * `ts.TypeChecker` (the feature IS the compiler integration — a fake exists
74
+ * only so `runCheckerPass`'s orchestration logic, persistence, and filtering
75
+ * can be unit-tested without paying real compiler cost; the classification
76
+ * logic itself is exercised only by the real implementation, in
77
+ * `checker-resolver.test.ts`'s real-compiler fixtures).
78
+ */
79
+ export interface TsProjectResolver {
80
+ discoverProjects(): TsProjectDiscoveryResult;
81
+ loadProgram(descriptor: TsProjectDescriptor): TsProjectHandle;
82
+ }
83
+ export declare class RealTsProjectResolver implements TsProjectResolver {
84
+ private readonly projectRoot;
85
+ constructor(projectRoot: string);
86
+ discoverProjects(): TsProjectDiscoveryResult;
87
+ loadProgram(descriptor: TsProjectDescriptor): TsProjectHandle;
88
+ }
89
+ export interface CheckerPassOptions {
90
+ /** DI seam for tests — defaults to `RealTsProjectResolver`. */
91
+ readonly resolver?: TsProjectResolver;
92
+ readonly onProject?: (configDir: string, index: number, total: number) => void;
93
+ }
94
+ export interface CheckerProjectTiming {
95
+ readonly configDir: string;
96
+ readonly fileCount: number;
97
+ readonly candidateCount: number;
98
+ readonly durationMs: number;
99
+ }
100
+ export interface CheckerPassResult {
101
+ readonly projectsChecked: number;
102
+ readonly projectsSkipped: readonly TsProjectSkip[];
103
+ readonly symbolsChecked: number;
104
+ /** Potential-match candidates whose file has no owning tsconfig project — left untouched, not silently dropped. */
105
+ readonly potentialSitesOutsideScope: number;
106
+ /** Distinct NEW edge rows actually inserted — not classification attempts
107
+ * (duplicates and already-heuristic-verified pairs collapse via the
108
+ * (from_id, to_id, edge_type) PK, so a rerun reports 0). */
109
+ readonly edgesUpgraded: number;
110
+ readonly classifiedDifferentDeclaration: number;
111
+ readonly classifiedNonCallSite: number;
112
+ readonly unresolved: number;
113
+ readonly perProjectTiming: readonly CheckerProjectTiming[];
114
+ /**
115
+ * Self-sampled peak RSS across the whole pass (`process.memoryUsage().rss`,
116
+ * polled every 250ms). This is an approximation, not the Stage 1.1 spike's
117
+ * external `ps`-on-a-child-process measurement — production runs in-process
118
+ * (the same one-shot-process reasoning `index-cmd.ts` uses throughout),
119
+ * and an in-process sampler can miss a spike inside a long synchronous
120
+ * stretch that never yields the event loop. Reported honestly as an
121
+ * approximation, not hidden.
122
+ */
123
+ readonly peakRssBytes: number;
124
+ readonly durationMs: number;
125
+ }
126
+ /**
127
+ * Run the checker pass over every tsconfig project in `config.resolved_project_root`.
128
+ *
129
+ * Two phases per project, kept strictly separate so the DB write lock is held
130
+ * in short batches (§7.6) rather than across the compiler-heavy classify loop:
131
+ * 1. Classify every candidate for the project against its `ts.Program` (no lock).
132
+ * 2. Flush the resulting edge/verdict writes under `structure.lock` (short batch).
133
+ */
134
+ /** One `files` row's identity and freshness stamp, keyed by path. */
135
+ export interface FileMeta {
136
+ readonly id: number;
137
+ readonly mtime: number;
138
+ }
139
+ /**
140
+ * Look up `files` rows for `paths` in one pass, batched under SQLite's bound
141
+ * parameter ceiling.
142
+ *
143
+ * Extracted from the checker pass so the batching is testable without standing
144
+ * up a TypeScript program: the path list is every distinct candidate file in
145
+ * one tsconfig project, accumulated across every symbol the pass examines, so
146
+ * nothing in its construction bounds it below SQLite's bound-parameter ceiling
147
+ * (`SQLITE_MAX_VARIABLES`, `./sqliteBatch.ts`). A single `IN` list past that
148
+ * ceiling throws `too many SQL variables` and fails
149
+ * the whole project's checker pass.
150
+ *
151
+ * Paths with no row are simply absent from the returned map — the caller
152
+ * already treats that as "file row vanished mid-run" and skips the candidate.
153
+ */
154
+ export declare function loadFileMetaByPath(db: Db, paths: readonly string[]): Promise<Map<string, FileMeta>>;
155
+ export declare function runCheckerPass(db: Db, chunkStore: Pick<ChunkStore, 'getAllChunks'>, config: ResolvedConfig, options?: CheckerPassOptions): Promise<CheckerPassResult>;
156
+ //# sourceMappingURL=checker-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker-resolver.d.ts","sourceRoot":"","sources":["../../src/graph/checker-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,458 @@
1
+ import { resolve, sep, dirname } from 'node:path';
2
+ import ts from 'typescript';
3
+ import fg from 'fast-glob';
4
+ import { withLock } from '../store/lock.js';
5
+ import { queryVerifiedCallers, querySymbolByName } from './queries.js';
6
+ import { collectPotentialMatchCandidates } from '../search/potential-matches.js';
7
+ import { chunkValuesForSqlite } from './sqliteBatch.js';
8
+ /**
9
+ * tsconfig.json locations that are structurally never real, standalone
10
+ * projects — excluded before even attempting to parse them so a large
11
+ * `node_modules` tree costs nothing.
12
+ */
13
+ const DISCOVERY_IGNORE = ['**/node_modules/**', '**/dist/**', '**/.build/**', '**/coverage/**'];
14
+ // Arrow-wrapped (not `ts.sys.fileExists` directly) so each call stays bound to
15
+ // `ts.sys` — @typescript-eslint/unbound-method flags a bare method reference
16
+ // as an unintentional-`this`-scoping risk.
17
+ const PARSE_CONFIG_HOST = {
18
+ fileExists: (path) => ts.sys.fileExists(path),
19
+ readFile: (path) => ts.sys.readFile(path),
20
+ readDirectory: (path, extensions, exclude, include, depth) => ts.sys.readDirectory(path, extensions, exclude, include, depth),
21
+ useCaseSensitiveFileNames: true,
22
+ };
23
+ /** Bound wrapper for `ts.sys.readFile`, passed where a bare function reference is needed. */
24
+ function readFile(path) {
25
+ return ts.sys.readFile(path);
26
+ }
27
+ /**
28
+ * Convert an absolute path to a POSIX-separated path relative to `root`.
29
+ * Returns `.` when `absPath` IS `root` (the fold-app-scale shape: a single
30
+ * package's own directory as project_root, tsconfig.json living directly in
31
+ * it — found running the real pass against align-kimik27-02/packages/core,
32
+ * IMPLEMENTATION_PLAN_VEXP.md Stage 1.2 addendum. Without this case the
33
+ * prefix-strip below never matches — `root` has no trailing slash to align
34
+ * against — and `configDir` came back as the full absolute path instead).
35
+ */
36
+ function relPath(absPath, root) {
37
+ const norm = absPath.split(sep).join('/');
38
+ const rootNorm = root.split(sep).join('/').replace(/\/$/, '');
39
+ if (norm === rootNorm)
40
+ return '.';
41
+ const withSlash = rootNorm + '/';
42
+ return norm.startsWith(withSlash) ? norm.slice(withSlash.length) : norm;
43
+ }
44
+ /**
45
+ * Enumerate every tsconfig project under `projectRoot`.
46
+ *
47
+ * A tsconfig.json is a real, checkable project when `ts.parseJsonConfigFileContent`
48
+ * resolves at least one source file for it. A base config meant to be
49
+ * `extends`-ed (e.g. `tsconfig.base.json`) declares no "include"/"files" of
50
+ * its own and resolves zero files — skipped with reason `no_include_base_config`.
51
+ * A config that fails to parse is skipped with the parser's own error text.
52
+ * This is a generic, project-shape-agnostic rule (unlike the Stage 1.1 spike's
53
+ * hardcoded 25-project list for the kluster monorepo specifically) so it works
54
+ * for any project `mast index --checker` runs against, monorepo or single-app.
55
+ */
56
+ export function discoverTsConfigProjects(projectRoot) {
57
+ const configPaths = fg
58
+ .sync('**/tsconfig.json', {
59
+ cwd: projectRoot,
60
+ ignore: DISCOVERY_IGNORE,
61
+ absolute: true,
62
+ onlyFiles: true,
63
+ followSymbolicLinks: false,
64
+ })
65
+ .sort();
66
+ const projects = [];
67
+ const skipped = [];
68
+ for (const configPath of configPaths) {
69
+ const configDir = relPath(dirname(configPath), projectRoot);
70
+ const configFile = ts.readConfigFile(configPath, readFile);
71
+ if (configFile.error !== undefined) {
72
+ skipped.push({
73
+ configDir,
74
+ reason: `tsconfig_parse_error: ${ts.flattenDiagnosticMessageText(configFile.error.messageText, '\n')}`,
75
+ });
76
+ continue;
77
+ }
78
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, PARSE_CONFIG_HOST, dirname(configPath));
79
+ if (parsed.fileNames.length === 0) {
80
+ skipped.push({ configDir, reason: 'no_include_base_config' });
81
+ continue;
82
+ }
83
+ projects.push({ configDir, fileNames: parsed.fileNames, compilerOptions: parsed.options });
84
+ }
85
+ return { projects, skipped };
86
+ }
87
+ /** Chunk `content` extends `context_lines` (default 3, MAST_SPEC §6.1) beyond
88
+ * strict AST boundaries — padding the identifier search window past that
89
+ * default with margin catches a call site sitting just outside
90
+ * [start_line, end_line] (Stage 1.1 spike finding: 10/50 samples
91
+ * false-classified as non-call-site before this pad was added). */
92
+ const CONTEXT_PAD = 5;
93
+ /** Bounded hop count for `ts.Symbol.getAliasedSymbol` chains. MANDATORY per
94
+ * the Stage 1.1 spike: without alias-following, `getSymbolAtLocation` on an
95
+ * imported identifier returns the local import binding (not its real
96
+ * target), and the definite-edge resolution rate collapses 38% -> 2%. */
97
+ const ALIAS_HOP_LIMIT = 8;
98
+ /** True when `node` is the callee of a CallExpression/NewExpression, direct or via `.property(...)`. */
99
+ function isCallShaped(node) {
100
+ const parent = node.parent;
101
+ if (parent === undefined)
102
+ return false;
103
+ if (ts.isCallExpression(parent) && parent.expression === node)
104
+ return true;
105
+ if (ts.isNewExpression(parent) && parent.expression === node)
106
+ return true;
107
+ if (ts.isPropertyAccessExpression(parent) && parent.name === node) {
108
+ const grandparent = parent.parent;
109
+ if (grandparent !== undefined && ts.isCallExpression(grandparent) && grandparent.expression === parent)
110
+ return true;
111
+ if (grandparent !== undefined && ts.isNewExpression(grandparent) && grandparent.expression === parent)
112
+ return true;
113
+ }
114
+ return false;
115
+ }
116
+ /**
117
+ * All `Identifier` nodes named `name` whose 1-indexed line falls in the
118
+ * padded `[startLine - pad, endLine + pad]` window, nearest-to-the-original-
119
+ * range first (ties broken by line, then source position — deterministic).
120
+ */
121
+ function findIdentifierOccurrences(sourceFile, name, startLine, endLine, pad) {
122
+ const occurrences = [];
123
+ const visit = (node) => {
124
+ if (ts.isIdentifier(node) && node.text === name) {
125
+ const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
126
+ const line1 = line + 1;
127
+ if (line1 >= startLine - pad && line1 <= endLine + pad) {
128
+ const distance = line1 < startLine ? startLine - line1 : line1 > endLine ? line1 - endLine : 0;
129
+ occurrences.push({ node, line: line1, distance, callShaped: isCallShaped(node) });
130
+ }
131
+ }
132
+ ts.forEachChild(node, visit);
133
+ };
134
+ visit(sourceFile);
135
+ occurrences.sort((a, b) => a.distance - b.distance || a.line - b.line || a.node.getStart(sourceFile) - b.node.getStart(sourceFile));
136
+ return occurrences;
137
+ }
138
+ class RealTsProjectHandle {
139
+ projectRoot;
140
+ program;
141
+ checker;
142
+ constructor(descriptor, projectRoot) {
143
+ this.projectRoot = projectRoot;
144
+ this.program = ts.createProgram({ rootNames: descriptor.fileNames, options: descriptor.compilerOptions });
145
+ this.checker = this.program.getTypeChecker();
146
+ }
147
+ classify(input) {
148
+ if (this.program === null || this.checker === null) {
149
+ throw new Error('RealTsProjectHandle.classify() called after dispose()');
150
+ }
151
+ const absPath = resolve(this.projectRoot, input.relFilePath).split(sep).join('/');
152
+ const sourceFile = this.program.getSourceFile(absPath);
153
+ // Defensive only: the orchestrator only routes candidates whose file was
154
+ // discovered as a member of THIS project's fileNames.
155
+ if (sourceFile === undefined)
156
+ return { kind: 'unresolved' };
157
+ const occurrences = findIdentifierOccurrences(sourceFile, input.bareName, input.startLine, input.endLine, CONTEXT_PAD);
158
+ const callSite = occurrences.find((o) => o.callShaped);
159
+ if (callSite === undefined)
160
+ return { kind: 'non_call_site' };
161
+ let symbol = this.checker.getSymbolAtLocation(callSite.node);
162
+ for (let hops = 0; symbol !== undefined && (symbol.flags & ts.SymbolFlags.Alias) !== 0 && hops < ALIAS_HOP_LIMIT; hops++) {
163
+ let aliased;
164
+ try {
165
+ aliased = this.checker.getAliasedSymbol(symbol);
166
+ }
167
+ catch {
168
+ break;
169
+ }
170
+ if (aliased === symbol)
171
+ break;
172
+ symbol = aliased;
173
+ }
174
+ const declarations = symbol?.getDeclarations() ?? [];
175
+ const firstDecl = declarations[0];
176
+ if (symbol === undefined || firstDecl === undefined)
177
+ return { kind: 'unresolved' };
178
+ const declSourceFile = firstDecl.getSourceFile();
179
+ const declLine = declSourceFile.getLineAndCharacterOfPosition(firstDecl.getStart(declSourceFile)).line + 1;
180
+ const declFilePath = relPath(resolve(declSourceFile.fileName), this.projectRoot);
181
+ const sameFile = declFilePath === input.queriedFilePath;
182
+ const lineClose = Math.abs(declLine - input.queriedLine) <= 3;
183
+ if (!(sameFile && lineClose))
184
+ return { kind: 'resolves_to_different' };
185
+ const lineText = sourceFile.getFullText().split('\n')[callSite.line - 1] ?? '';
186
+ return { kind: 'resolves_to_queried', callLine: callSite.line, context: lineText.trim() };
187
+ }
188
+ dispose() {
189
+ // Drop references so nothing keeps this project's Program (and the
190
+ // source ASTs/type graph it retains) alive once the orchestrator moves to
191
+ // the next project — the Stage 1.1 Q2 anomaly (hold-all-programs made
192
+ // "warm" 2x slower than cold via GC pressure) is what this guards against.
193
+ this.program = null;
194
+ this.checker = null;
195
+ }
196
+ }
197
+ export class RealTsProjectResolver {
198
+ projectRoot;
199
+ constructor(projectRoot) {
200
+ this.projectRoot = projectRoot;
201
+ }
202
+ discoverProjects() {
203
+ return discoverTsConfigProjects(this.projectRoot);
204
+ }
205
+ loadProgram(descriptor) {
206
+ return new RealTsProjectHandle(descriptor, this.projectRoot);
207
+ }
208
+ }
209
+ /** `queried.name` may be qualified (`ClassName.methodName`, §9 mast_signature convention) — only the bare name is a real identifier token. */
210
+ function bareName(name) {
211
+ const parts = name.split('.');
212
+ return parts[parts.length - 1] ?? name;
213
+ }
214
+ /**
215
+ * Look up `files` rows for `paths` in one pass, batched under SQLite's bound
216
+ * parameter ceiling.
217
+ *
218
+ * Extracted from the checker pass so the batching is testable without standing
219
+ * up a TypeScript program: the path list is every distinct candidate file in
220
+ * one tsconfig project, accumulated across every symbol the pass examines, so
221
+ * nothing in its construction bounds it below SQLite's bound-parameter ceiling
222
+ * (`SQLITE_MAX_VARIABLES`, `./sqliteBatch.ts`). A single `IN` list past that
223
+ * ceiling throws `too many SQL variables` and fails
224
+ * the whole project's checker pass.
225
+ *
226
+ * Paths with no row are simply absent from the returned map — the caller
227
+ * already treats that as "file row vanished mid-run" and skips the candidate.
228
+ */
229
+ export async function loadFileMetaByPath(db, paths) {
230
+ const meta = new Map();
231
+ for (const batch of chunkValuesForSqlite(paths)) {
232
+ const rows = await db
233
+ .selectFrom('files')
234
+ .select(['id', 'path', 'mtime'])
235
+ .where('path', 'in', [...batch])
236
+ .execute();
237
+ for (const r of rows)
238
+ meta.set(r.path, { id: r.id, mtime: r.mtime });
239
+ }
240
+ return meta;
241
+ }
242
+ export async function runCheckerPass(db, chunkStore, config, options = {}) {
243
+ const startMs = Date.now();
244
+ const resolver = options.resolver ?? new RealTsProjectResolver(config.resolved_project_root);
245
+ let peakRssBytes = process.memoryUsage().rss;
246
+ const rssTimer = setInterval(() => {
247
+ const rss = process.memoryUsage().rss;
248
+ if (rss > peakRssBytes)
249
+ peakRssBytes = rss;
250
+ }, 250);
251
+ try {
252
+ const { projects, skipped } = resolver.discoverProjects();
253
+ // --- Phase A: gather candidates (pure DB/FTS reads, no compiler) ---
254
+ const allSymbols = await db
255
+ .selectFrom('symbols as s')
256
+ .innerJoin('files as f', 'f.id', 's.file_id')
257
+ .select(['s.id', 's.name', 'f.path as file_path', 's.line'])
258
+ .where('s.kind', '!=', 'export')
259
+ .execute();
260
+ const fileToProject = new Map();
261
+ for (const project of projects) {
262
+ for (const absFile of project.fileNames) {
263
+ const rel = relPath(absFile, config.resolved_project_root);
264
+ if (!fileToProject.has(rel))
265
+ fileToProject.set(rel, project);
266
+ }
267
+ }
268
+ const byProject = new Map();
269
+ let potentialSitesOutsideScope = 0;
270
+ // One full chunk scan up front, then Map lookups. Candidate collection
271
+ // runs once per indexed symbol below; fetching chunks one-by-one instead
272
+ // was measured at 50+ CPU-minutes on this monorepo (10,733 symbols)
273
+ // without completing Phase A. Semantics are identical —
274
+ // `collectPotentialMatchCandidates` only needs "chunks by id".
275
+ const allChunks = await chunkStore.getAllChunks();
276
+ const chunkById = new Map(allChunks.map((c) => [c.chunk_id, c]));
277
+ const chunkSource = {
278
+ getChunksByIds: (ids) => Promise.resolve(ids.flatMap((id) => {
279
+ const chunk = chunkById.get(id);
280
+ return chunk === undefined ? [] : [chunk];
281
+ })),
282
+ };
283
+ for (const sym of allSymbols) {
284
+ const verifiedRows = await queryVerifiedCallers(db, sym.id, false);
285
+ const verified = verifiedRows.map((r) => ({
286
+ file_path: r.file_path,
287
+ line: r.line,
288
+ caller_symbol: r.caller_symbol,
289
+ context: r.context,
290
+ resolution: r.resolution,
291
+ }));
292
+ // F10 (Stage 3): collectPotentialMatchCandidates now also returns an
293
+ // optional truncatedMatchCount — Phase A has no use for it (it isn't a
294
+ // tool-response summary), so it's destructured away and ignored here.
295
+ const { candidates } = await collectPotentialMatchCandidates(db, chunkSource, sym.name, verified);
296
+ for (const c of candidates) {
297
+ const project = fileToProject.get(c.file_path);
298
+ if (project === undefined) {
299
+ potentialSitesOutsideScope++;
300
+ continue;
301
+ }
302
+ const bucket = byProject.get(project.configDir) ?? [];
303
+ bucket.push({
304
+ symbolId: sym.id,
305
+ symbolName: sym.name,
306
+ queriedFilePath: sym.file_path,
307
+ queriedLine: sym.line,
308
+ candidateFilePath: c.file_path,
309
+ startLine: c.start_line,
310
+ endLine: c.end_line,
311
+ chunkSymbolName: c.chunk_symbol_name,
312
+ });
313
+ byProject.set(project.configDir, bucket);
314
+ }
315
+ }
316
+ // --- Phase B: classify project by project, ONE ts.Program at a time ---
317
+ let edgesUpgraded = 0;
318
+ let classifiedDifferentDeclaration = 0;
319
+ let classifiedNonCallSite = 0;
320
+ let unresolved = 0;
321
+ const perProjectTiming = [];
322
+ for (let i = 0; i < projects.length; i++) {
323
+ const project = projects[i];
324
+ options.onProject?.(project.configDir, i + 1, projects.length);
325
+ const bucket = byProject.get(project.configDir);
326
+ if (bucket === undefined || bucket.length === 0)
327
+ continue; // nothing to check — don't pay program cost
328
+ const t0 = Date.now();
329
+ const handle = resolver.loadProgram(project);
330
+ const pending = [];
331
+ try {
332
+ // File id/mtime cache — one query for the whole project's bucket
333
+ // instead of one per candidate.
334
+ const filePaths = [...new Set(bucket.map((c) => c.candidateFilePath))];
335
+ const fileMeta = await loadFileMetaByPath(db, filePaths);
336
+ for (const c of bucket) {
337
+ const meta = fileMeta.get(c.candidateFilePath);
338
+ if (meta === undefined)
339
+ continue; // file row vanished mid-run — defensive
340
+ const result = handle.classify({
341
+ relFilePath: c.candidateFilePath,
342
+ bareName: bareName(c.symbolName),
343
+ startLine: c.startLine,
344
+ endLine: c.endLine,
345
+ queriedFilePath: c.queriedFilePath,
346
+ queriedLine: c.queriedLine,
347
+ });
348
+ if (result.kind === 'unresolved') {
349
+ unresolved++;
350
+ continue;
351
+ }
352
+ // Every non-'unresolved' outcome gets a verdict row keyed by the
353
+ // candidate's OWN chunk identity (not the checker's more-precise
354
+ // call line) — this must match collectPotentialMatchCandidates'
355
+ // dedup key exactly, see _helpers.ts.
356
+ pending.push({
357
+ kind: 'verdict',
358
+ queriedSymbolId: c.symbolId,
359
+ fileId: meta.id,
360
+ line: c.startLine,
361
+ verdict: result.kind,
362
+ mtime: meta.mtime,
363
+ });
364
+ if (result.kind === 'non_call_site') {
365
+ classifiedNonCallSite++;
366
+ continue;
367
+ }
368
+ if (result.kind === 'resolves_to_different') {
369
+ classifiedDifferentDeclaration++;
370
+ continue;
371
+ }
372
+ // result.kind === 'resolves_to_queried' — write the caller edge too,
373
+ // but only when the call site sits inside a chunk with a real
374
+ // enclosing symbol. Top-level block code has none (chunk_symbol_name
375
+ // is null) — a narrow, documented gap: still classified (so it never
376
+ // re-surfaces as a review site), just not upgraded to a graph edge,
377
+ // because there is no valid `from_id` to write one against.
378
+ if (c.chunkSymbolName === null)
379
+ continue;
380
+ const [fromSymbol] = await querySymbolByName(db, c.chunkSymbolName, c.candidateFilePath);
381
+ if (fromSymbol === undefined)
382
+ continue;
383
+ pending.push({ kind: 'edge', fromId: fromSymbol.id, toId: c.symbolId, callLine: result.callLine, context: result.context });
384
+ }
385
+ }
386
+ finally {
387
+ handle.dispose();
388
+ }
389
+ // --- Flush this project's writes in one short lock-held batch (§7.6) ---
390
+ if (pending.length > 0) {
391
+ await withLock(config.resolved_state_dir, 'structure', { maxRetries: 5, retryIntervalMs: 1_000, caller: 'checker-resolver' }, async () => {
392
+ for (const w of pending) {
393
+ if (w.kind === 'verdict') {
394
+ await db
395
+ .insertInto('checker_verdicts')
396
+ .values({
397
+ queried_symbol_id: w.queriedSymbolId,
398
+ call_site_file_id: w.fileId,
399
+ call_site_line: w.line,
400
+ verdict: w.verdict,
401
+ call_site_mtime: w.mtime,
402
+ })
403
+ .onConflict((oc) => oc.columns(['queried_symbol_id', 'call_site_file_id', 'call_site_line']).doUpdateSet((eb) => ({
404
+ verdict: eb.ref('excluded.verdict'),
405
+ call_site_mtime: eb.ref('excluded.call_site_mtime'),
406
+ })))
407
+ .execute();
408
+ }
409
+ else {
410
+ const [insert] = await db
411
+ .insertInto('edges')
412
+ .values({
413
+ from_id: w.fromId,
414
+ to_id: w.toId,
415
+ edge_type: 'POTENTIAL_CALL',
416
+ resolution: 'checker',
417
+ call_line: w.callLine,
418
+ context: w.context,
419
+ })
420
+ .onConflict((oc) => oc.doNothing())
421
+ .execute();
422
+ // `edgesUpgraded` reports rows that actually landed, not
423
+ // classification attempts: ON CONFLICT collapses duplicate
424
+ // (from,to) pairs (several call sites in one caller) and edges a
425
+ // heuristic rule already verified — on the monorepo validation
426
+ // run, 3,935 attempts collapsed to 1,885 distinct rows. A rerun
427
+ // therefore honestly reports 0.
428
+ edgesUpgraded += Number(insert?.numInsertedOrUpdatedRows ?? 0n);
429
+ }
430
+ }
431
+ });
432
+ }
433
+ perProjectTiming.push({
434
+ configDir: project.configDir,
435
+ fileCount: project.fileNames.length,
436
+ candidateCount: bucket.length,
437
+ durationMs: Date.now() - t0,
438
+ });
439
+ }
440
+ return {
441
+ projectsChecked: perProjectTiming.length,
442
+ projectsSkipped: skipped,
443
+ symbolsChecked: allSymbols.length,
444
+ potentialSitesOutsideScope,
445
+ edgesUpgraded,
446
+ classifiedDifferentDeclaration,
447
+ classifiedNonCallSite,
448
+ unresolved,
449
+ perProjectTiming,
450
+ peakRssBytes,
451
+ durationMs: Date.now() - startMs,
452
+ };
453
+ }
454
+ finally {
455
+ clearInterval(rssTimer);
456
+ }
457
+ }
458
+ //# sourceMappingURL=checker-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker-resolver.js","sourceRoot":"","sources":["../../src/graph/checker-resolver.ts"],"names":[],"mappings":"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"}