@monoes/monograph 1.5.2 → 1.5.4

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 (504) hide show
  1. package/.monodesign/hook.cache.json +1 -1
  2. package/__tests__/integration/build-atomicity.test.ts +61 -0
  3. package/__tests__/integration/call-attribution.test.ts +116 -0
  4. package/coverage/base.css +224 -0
  5. package/coverage/block-navigation.js +87 -0
  6. package/coverage/coverage-summary.json +399 -0
  7. package/coverage/favicon.png +0 -0
  8. package/coverage/index.html +881 -0
  9. package/coverage/prettify.css +1 -0
  10. package/coverage/prettify.js +2 -0
  11. package/coverage/sort-arrow-sprite.png +0 -0
  12. package/coverage/sorter.js +210 -0
  13. package/coverage/src/analysis/benchmark.ts.html +481 -0
  14. package/coverage/src/analysis/changed-files.ts.html +304 -0
  15. package/coverage/src/analysis/changed-workspaces.ts.html +367 -0
  16. package/coverage/src/analysis/churn-cache.ts.html +622 -0
  17. package/coverage/src/analysis/churn-trend.ts.html +256 -0
  18. package/coverage/src/analysis/churn.ts.html +874 -0
  19. package/coverage/src/analysis/cluster-quality.ts.html +511 -0
  20. package/coverage/src/analysis/combined.ts.html +208 -0
  21. package/coverage/src/analysis/corpus-health.ts.html +208 -0
  22. package/coverage/src/analysis/coverage-gaps.ts.html +823 -0
  23. package/coverage/src/analysis/dep-classification.ts.html +586 -0
  24. package/coverage/src/analysis/dependency-health.ts.html +523 -0
  25. package/coverage/src/analysis/duplicate-exports.ts.html +415 -0
  26. package/coverage/src/analysis/fallow-suppression.ts.html +379 -0
  27. package/coverage/src/analysis/feature-flags-config.ts.html +226 -0
  28. package/coverage/src/analysis/feature-flags.ts.html +754 -0
  29. package/coverage/src/analysis/file-classifier.ts.html +346 -0
  30. package/coverage/src/analysis/git-changed-files.ts.html +271 -0
  31. package/coverage/src/analysis/health-baseline.ts.html +325 -0
  32. package/coverage/src/analysis/index.html +641 -0
  33. package/coverage/src/analysis/issue-filters.ts.html +253 -0
  34. package/coverage/src/analysis/list.ts.html +307 -0
  35. package/coverage/src/analysis/node-similarity.ts.html +430 -0
  36. package/coverage/src/analysis/private-type-leaks.ts.html +442 -0
  37. package/coverage/src/analysis/progress.ts.html +214 -0
  38. package/coverage/src/analysis/project-state.ts.html +370 -0
  39. package/coverage/src/analysis/regression-config.ts.html +193 -0
  40. package/coverage/src/analysis/rule-overrides.ts.html +328 -0
  41. package/coverage/src/analysis/scripts.ts.html +370 -0
  42. package/coverage/src/analysis/shape-extractor.ts.html +691 -0
  43. package/coverage/src/analysis/since-duration.ts.html +211 -0
  44. package/coverage/src/analysis/suppression-context.ts.html +370 -0
  45. package/coverage/src/analysis/suppressions.ts.html +325 -0
  46. package/coverage/src/analysis/surprise-scorer.ts.html +307 -0
  47. package/coverage/src/analysis/targets.ts.html +796 -0
  48. package/coverage/src/analysis/unused-class-members.ts.html +322 -0
  49. package/coverage/src/analysis/workspace-filter.ts.html +352 -0
  50. package/coverage/src/analyze/boundary-analysis.ts.html +472 -0
  51. package/coverage/src/analyze/index.html +161 -0
  52. package/coverage/src/analyze/predicates/file.ts.html +343 -0
  53. package/coverage/src/analyze/predicates/import.ts.html +355 -0
  54. package/coverage/src/analyze/predicates/index.html +146 -0
  55. package/coverage/src/analyze/predicates/lifecycle.ts.html +250 -0
  56. package/coverage/src/analyze/unused-deps.ts.html +295 -0
  57. package/coverage/src/analyze/unused-exports.ts.html +520 -0
  58. package/coverage/src/analyze/unused-files.ts.html +223 -0
  59. package/coverage/src/api/index.html +131 -0
  60. package/coverage/src/api/production-override.ts.html +274 -0
  61. package/coverage/src/api/programmatic.ts.html +439 -0
  62. package/coverage/src/audit.ts.html +787 -0
  63. package/coverage/src/cache/augment-cache.ts.html +274 -0
  64. package/coverage/src/cache/extraction-cache.ts.html +508 -0
  65. package/coverage/src/cache/index.html +131 -0
  66. package/coverage/src/check/filtering.ts.html +319 -0
  67. package/coverage/src/check/index.html +161 -0
  68. package/coverage/src/check/index.ts.html +382 -0
  69. package/coverage/src/check/output.ts.html +322 -0
  70. package/coverage/src/check/rules.ts.html +268 -0
  71. package/coverage/src/ci-template.ts.html +337 -0
  72. package/coverage/src/claude-cli.ts.html +262 -0
  73. package/coverage/src/cli/ai-context.ts.html +664 -0
  74. package/coverage/src/cli/augment.ts.html +427 -0
  75. package/coverage/src/cli/check-update.ts.html +205 -0
  76. package/coverage/src/cli/doctor.ts.html +631 -0
  77. package/coverage/src/cli/eval-server.ts.html +463 -0
  78. package/coverage/src/cli/hooks-install.ts.html +691 -0
  79. package/coverage/src/cli/index.html +221 -0
  80. package/coverage/src/cli/setup.ts.html +676 -0
  81. package/coverage/src/cli/skill-gen.ts.html +1126 -0
  82. package/coverage/src/commands/flags.ts.html +301 -0
  83. package/coverage/src/commands/index.html +116 -0
  84. package/coverage/src/config/boundary-config.ts.html +634 -0
  85. package/coverage/src/config/cli-schema.ts.html +328 -0
  86. package/coverage/src/config/config-parsing.ts.html +391 -0
  87. package/coverage/src/config/duplicates-config.ts.html +271 -0
  88. package/coverage/src/config/external-plugin.ts.html +316 -0
  89. package/coverage/src/config/health-config.ts.html +211 -0
  90. package/coverage/src/config/ignore-exports-used-in-file.ts.html +223 -0
  91. package/coverage/src/config/index.html +341 -0
  92. package/coverage/src/config/migration-types.ts.html +304 -0
  93. package/coverage/src/config/output-format.ts.html +157 -0
  94. package/coverage/src/config/plugins/builtin.ts.html +1318 -0
  95. package/coverage/src/config/plugins/index.html +146 -0
  96. package/coverage/src/config/plugins/registry.ts.html +316 -0
  97. package/coverage/src/config/plugins/types.ts.html +127 -0
  98. package/coverage/src/config/resolution.ts.html +391 -0
  99. package/coverage/src/config/rules.ts.html +295 -0
  100. package/coverage/src/config/schema-gen.ts.html +430 -0
  101. package/coverage/src/config/types.ts.html +532 -0
  102. package/coverage/src/config/used-class-members.ts.html +244 -0
  103. package/coverage/src/config/validate.ts.html +409 -0
  104. package/coverage/src/config/workspace.ts.html +496 -0
  105. package/coverage/src/coverage/cloud-client.ts.html +418 -0
  106. package/coverage/src/coverage/index.html +146 -0
  107. package/coverage/src/coverage/upload-inventory.ts.html +337 -0
  108. package/coverage/src/coverage/upload-source-maps.ts.html +376 -0
  109. package/coverage/src/discover/entry-points.ts.html +238 -0
  110. package/coverage/src/discover/index.html +131 -0
  111. package/coverage/src/discover/infrastructure-entries.ts.html +610 -0
  112. package/coverage/src/duplicates/detect/concatenation.ts.html +196 -0
  113. package/coverage/src/duplicates/detect/extraction.ts.html +406 -0
  114. package/coverage/src/duplicates/detect/filtering.ts.html +421 -0
  115. package/coverage/src/duplicates/detect/index.html +206 -0
  116. package/coverage/src/duplicates/detect/lcp.ts.html +166 -0
  117. package/coverage/src/duplicates/detect/ranking.ts.html +133 -0
  118. package/coverage/src/duplicates/detect/statistics.ts.html +292 -0
  119. package/coverage/src/duplicates/detect/suffix-array.ts.html +349 -0
  120. package/coverage/src/duplicates/families.ts.html +370 -0
  121. package/coverage/src/duplicates/index.html +161 -0
  122. package/coverage/src/duplicates/normalize.ts.html +259 -0
  123. package/coverage/src/duplicates/shingle-filter.ts.html +196 -0
  124. package/coverage/src/duplicates/token-types.ts.html +271 -0
  125. package/coverage/src/duplicates/tokenize/index.html +116 -0
  126. package/coverage/src/duplicates/tokenize/index.ts.html +397 -0
  127. package/coverage/src/error/fallow-error.ts.html +367 -0
  128. package/coverage/src/error/index.html +116 -0
  129. package/coverage/src/error.ts.html +226 -0
  130. package/coverage/src/export/adjacency-matrix.ts.html +466 -0
  131. package/coverage/src/export/analysis-json.ts.html +346 -0
  132. package/coverage/src/export/badge.ts.html +400 -0
  133. package/coverage/src/export/canvas.ts.html +211 -0
  134. package/coverage/src/export/codeclimate.ts.html +688 -0
  135. package/coverage/src/export/compact-health.ts.html +442 -0
  136. package/coverage/src/export/compact.ts.html +334 -0
  137. package/coverage/src/export/csv.ts.html +184 -0
  138. package/coverage/src/export/cypher.ts.html +184 -0
  139. package/coverage/src/export/dot.ts.html +241 -0
  140. package/coverage/src/export/gexf.ts.html +262 -0
  141. package/coverage/src/export/graphml.ts.html +235 -0
  142. package/coverage/src/export/html.ts.html +1729 -0
  143. package/coverage/src/export/index.html +401 -0
  144. package/coverage/src/export/index.ts.html +112 -0
  145. package/coverage/src/export/json.ts.html +193 -0
  146. package/coverage/src/export/markdown.ts.html +955 -0
  147. package/coverage/src/export/mermaid.ts.html +385 -0
  148. package/coverage/src/export/obsidian.ts.html +217 -0
  149. package/coverage/src/export/sarif.ts.html +820 -0
  150. package/coverage/src/export/svg.ts.html +289 -0
  151. package/coverage/src/fix/deps.ts.html +295 -0
  152. package/coverage/src/fix/enum-members.ts.html +394 -0
  153. package/coverage/src/fix/export-surgery.ts.html +676 -0
  154. package/coverage/src/fix/exports.ts.html +364 -0
  155. package/coverage/src/fix/index.html +176 -0
  156. package/coverage/src/fix/orchestrator.ts.html +286 -0
  157. package/coverage/src/graph/analyzer.ts.html +292 -0
  158. package/coverage/src/graph/author-analytics.ts.html +736 -0
  159. package/coverage/src/graph/baseline.ts.html +1381 -0
  160. package/coverage/src/graph/clone-families.ts.html +481 -0
  161. package/coverage/src/graph/codeowners-extended.ts.html +427 -0
  162. package/coverage/src/graph/codeowners-gitlab.ts.html +535 -0
  163. package/coverage/src/graph/codeowners.ts.html +736 -0
  164. package/coverage/src/graph/complexity.ts.html +685 -0
  165. package/coverage/src/graph/cross-reference-findings.ts.html +340 -0
  166. package/coverage/src/graph/cross-reference.ts.html +502 -0
  167. package/coverage/src/graph/cycle-detection.ts.html +1018 -0
  168. package/coverage/src/graph/cycles.ts.html +751 -0
  169. package/coverage/src/graph/dead-code.ts.html +469 -0
  170. package/coverage/src/graph/dependency-closure.ts.html +463 -0
  171. package/coverage/src/graph/dfs.ts.html +439 -0
  172. package/coverage/src/graph/diff.ts.html +361 -0
  173. package/coverage/src/graph/duplication-stats.ts.html +322 -0
  174. package/coverage/src/graph/edge-filter.ts.html +436 -0
  175. package/coverage/src/graph/explain.ts.html +484 -0
  176. package/coverage/src/graph/external-style-usage.ts.html +328 -0
  177. package/coverage/src/graph/health-score.ts.html +622 -0
  178. package/coverage/src/graph/hotspots.ts.html +742 -0
  179. package/coverage/src/graph/import-chain.ts.html +529 -0
  180. package/coverage/src/graph/index.html +746 -0
  181. package/coverage/src/graph/loader.ts.html +217 -0
  182. package/coverage/src/graph/maintainability.ts.html +553 -0
  183. package/coverage/src/graph/merge.ts.html +607 -0
  184. package/coverage/src/graph/mirrored-dirs.ts.html +691 -0
  185. package/coverage/src/graph/narrowing.ts.html +361 -0
  186. package/coverage/src/graph/node-search.ts.html +688 -0
  187. package/coverage/src/graph/node-types.ts.html +286 -0
  188. package/coverage/src/graph/normalize-id.ts.html +499 -0
  189. package/coverage/src/graph/pagerank.ts.html +580 -0
  190. package/coverage/src/graph/prune.ts.html +370 -0
  191. package/coverage/src/graph/re-exports/index.html +116 -0
  192. package/coverage/src/graph/re-exports/propagate.ts.html +370 -0
  193. package/coverage/src/graph/reachability.ts.html +382 -0
  194. package/coverage/src/graph/regex-search.ts.html +781 -0
  195. package/coverage/src/graph/regression.ts.html +682 -0
  196. package/coverage/src/graph/resolve/discover-types.ts.html +220 -0
  197. package/coverage/src/graph/resolve/dynamic-imports.ts.html +391 -0
  198. package/coverage/src/graph/resolve/fallbacks.ts.html +322 -0
  199. package/coverage/src/graph/resolve/index.html +281 -0
  200. package/coverage/src/graph/resolve/index.ts.html +289 -0
  201. package/coverage/src/graph/resolve/path-info.ts.html +208 -0
  202. package/coverage/src/graph/resolve/re-exports.ts.html +127 -0
  203. package/coverage/src/graph/resolve/react-native.ts.html +166 -0
  204. package/coverage/src/graph/resolve/require-imports.ts.html +139 -0
  205. package/coverage/src/graph/resolve/specifier.ts.html +445 -0
  206. package/coverage/src/graph/resolve/static-imports.ts.html +127 -0
  207. package/coverage/src/graph/resolve/types.ts.html +409 -0
  208. package/coverage/src/graph/resolve/upgrades.ts.html +181 -0
  209. package/coverage/src/graph/ripple-impact.ts.html +478 -0
  210. package/coverage/src/graph/risk-profile.ts.html +622 -0
  211. package/coverage/src/graph/statistics.ts.html +580 -0
  212. package/coverage/src/graph/stats.ts.html +556 -0
  213. package/coverage/src/graph/subgraph.ts.html +571 -0
  214. package/coverage/src/graph/topo-sort.ts.html +598 -0
  215. package/coverage/src/graph/wcc.ts.html +646 -0
  216. package/coverage/src/groups/contract-bridge.ts.html +394 -0
  217. package/coverage/src/groups/contract-registry.ts.html +874 -0
  218. package/coverage/src/groups/group-config.ts.html +409 -0
  219. package/coverage/src/groups/group-search.ts.html +502 -0
  220. package/coverage/src/groups/group-sync.ts.html +331 -0
  221. package/coverage/src/groups/grpc-extractor.ts.html +277 -0
  222. package/coverage/src/groups/index.html +221 -0
  223. package/coverage/src/groups/service-boundary.ts.html +442 -0
  224. package/coverage/src/groups/topic-extractor.ts.html +355 -0
  225. package/coverage/src/health/analysis-counts-snapshot.ts.html +256 -0
  226. package/coverage/src/health/analysis-counts.ts.html +295 -0
  227. package/coverage/src/health/complexity-findings.ts.html +430 -0
  228. package/coverage/src/health/distribution-thresholds.ts.html +247 -0
  229. package/coverage/src/health/grouping.ts.html +499 -0
  230. package/coverage/src/health/health-grouping.ts.html +343 -0
  231. package/coverage/src/health/health-report-types.ts.html +580 -0
  232. package/coverage/src/health/health-report.ts.html +328 -0
  233. package/coverage/src/health/health-score.ts.html +280 -0
  234. package/coverage/src/health/hotspot-utils.ts.html +250 -0
  235. package/coverage/src/health/hotspots.ts.html +397 -0
  236. package/coverage/src/health/index.html +551 -0
  237. package/coverage/src/health/large-functions.ts.html +187 -0
  238. package/coverage/src/health/ownership-metrics.ts.html +268 -0
  239. package/coverage/src/health/ownership-risk.ts.html +379 -0
  240. package/coverage/src/health/ownership.ts.html +607 -0
  241. package/coverage/src/health/quality-gate.ts.html +256 -0
  242. package/coverage/src/health/risk-profile.ts.html +202 -0
  243. package/coverage/src/health/runtime-coverage-report.ts.html +388 -0
  244. package/coverage/src/health/runtime-coverage.ts.html +298 -0
  245. package/coverage/src/health/scores.ts.html +301 -0
  246. package/coverage/src/health/scoring-types.ts.html +229 -0
  247. package/coverage/src/health/target-thresholds.ts.html +361 -0
  248. package/coverage/src/health/target-types.ts.html +247 -0
  249. package/coverage/src/health/targets.ts.html +538 -0
  250. package/coverage/src/health/timings.ts.html +343 -0
  251. package/coverage/src/health/trend-types.ts.html +256 -0
  252. package/coverage/src/health/trends.ts.html +343 -0
  253. package/coverage/src/health/vital-signs-compute.ts.html +409 -0
  254. package/coverage/src/health/vital-signs-snapshot.ts.html +301 -0
  255. package/coverage/src/health/vital-signs.ts.html +388 -0
  256. package/coverage/src/index.html +191 -0
  257. package/coverage/src/index.ts.html +418 -0
  258. package/coverage/src/ingest/git-clone.ts.html +823 -0
  259. package/coverage/src/ingest/index.html +161 -0
  260. package/coverage/src/ingest/query-memory.ts.html +481 -0
  261. package/coverage/src/ingest/transcribe.ts.html +847 -0
  262. package/coverage/src/ingest/url-ingest.ts.html +346 -0
  263. package/coverage/src/init/agent-hooks.ts.html +343 -0
  264. package/coverage/src/init/git-hooks.ts.html +298 -0
  265. package/coverage/src/init/index.html +146 -0
  266. package/coverage/src/init/project-detection.ts.html +400 -0
  267. package/coverage/src/license/index.html +116 -0
  268. package/coverage/src/license/manager.ts.html +445 -0
  269. package/coverage/src/lsp/code-actions.ts.html +466 -0
  270. package/coverage/src/lsp/code-lens.ts.html +253 -0
  271. package/coverage/src/lsp/diagnostics-ext.ts.html +535 -0
  272. package/coverage/src/lsp/diagnostics-push.ts.html +394 -0
  273. package/coverage/src/lsp/diagnostics.ts.html +379 -0
  274. package/coverage/src/lsp/hover.ts.html +277 -0
  275. package/coverage/src/lsp/index.html +206 -0
  276. package/coverage/src/lsp/server.ts.html +847 -0
  277. package/coverage/src/mcp/index.html +146 -0
  278. package/coverage/src/mcp/params.ts.html +688 -0
  279. package/coverage/src/mcp/resources.ts.html +457 -0
  280. package/coverage/src/mcp/tool-builders.ts.html +694 -0
  281. package/coverage/src/mcp-resources/communities-resource.ts.html +301 -0
  282. package/coverage/src/mcp-resources/graph-resource.ts.html +127 -0
  283. package/coverage/src/mcp-resources/index.html +251 -0
  284. package/coverage/src/mcp-resources/index.ts.html +112 -0
  285. package/coverage/src/mcp-resources/named-cluster-resource.ts.html +190 -0
  286. package/coverage/src/mcp-resources/named-process-resource.ts.html +163 -0
  287. package/coverage/src/mcp-resources/processes-resource.ts.html +286 -0
  288. package/coverage/src/mcp-resources/repo-context-resource.ts.html +193 -0
  289. package/coverage/src/mcp-resources/repos-resource.ts.html +148 -0
  290. package/coverage/src/mcp-resources/schema-resource.ts.html +223 -0
  291. package/coverage/src/mcp-resources/wiki-resource.ts.html +154 -0
  292. package/coverage/src/mcp-tools/api-impact.ts.html +628 -0
  293. package/coverage/src/mcp-tools/context.ts.html +418 -0
  294. package/coverage/src/mcp-tools/cypher.ts.html +172 -0
  295. package/coverage/src/mcp-tools/detect-changes.ts.html +433 -0
  296. package/coverage/src/mcp-tools/explain.ts.html +280 -0
  297. package/coverage/src/mcp-tools/graph-query.ts.html +469 -0
  298. package/coverage/src/mcp-tools/group-list.ts.html +349 -0
  299. package/coverage/src/mcp-tools/group-query.ts.html +163 -0
  300. package/coverage/src/mcp-tools/group-sync.ts.html +181 -0
  301. package/coverage/src/mcp-tools/impact.ts.html +691 -0
  302. package/coverage/src/mcp-tools/index.html +431 -0
  303. package/coverage/src/mcp-tools/index.ts.html +148 -0
  304. package/coverage/src/mcp-tools/list-repos.ts.html +199 -0
  305. package/coverage/src/mcp-tools/neighbors.ts.html +325 -0
  306. package/coverage/src/mcp-tools/query.ts.html +343 -0
  307. package/coverage/src/mcp-tools/rename.ts.html +439 -0
  308. package/coverage/src/mcp-tools/route-map.ts.html +379 -0
  309. package/coverage/src/mcp-tools/serve.ts.html +208 -0
  310. package/coverage/src/mcp-tools/shape-check.ts.html +631 -0
  311. package/coverage/src/mcp-tools/staleness.ts.html +124 -0
  312. package/coverage/src/mcp-tools/tool-map.ts.html +283 -0
  313. package/coverage/src/mcp-tools/wiki-build.ts.html +196 -0
  314. package/coverage/src/mcp-tools/wiki.ts.html +169 -0
  315. package/coverage/src/migrate/index.html +161 -0
  316. package/coverage/src/migrate/jscpd.ts.html +319 -0
  317. package/coverage/src/migrate/jsonc-gen.ts.html +199 -0
  318. package/coverage/src/migrate/knip.ts.html +463 -0
  319. package/coverage/src/migrate/toml-gen.ts.html +229 -0
  320. package/coverage/src/parsers/c.ts.html +178 -0
  321. package/coverage/src/parsers/cpp.ts.html +172 -0
  322. package/coverage/src/parsers/csharp.ts.html +214 -0
  323. package/coverage/src/parsers/dart.ts.html +202 -0
  324. package/coverage/src/parsers/extractor.ts.html +691 -0
  325. package/coverage/src/parsers/go.ts.html +166 -0
  326. package/coverage/src/parsers/index.html +386 -0
  327. package/coverage/src/parsers/java.ts.html +166 -0
  328. package/coverage/src/parsers/kotlin.ts.html +193 -0
  329. package/coverage/src/parsers/language-config.ts.html +169 -0
  330. package/coverage/src/parsers/language-parsers.ts.html +445 -0
  331. package/coverage/src/parsers/loader.ts.html +532 -0
  332. package/coverage/src/parsers/named-bindings.ts.html +274 -0
  333. package/coverage/src/parsers/php.ts.html +196 -0
  334. package/coverage/src/parsers/python.ts.html +163 -0
  335. package/coverage/src/parsers/ruby.ts.html +202 -0
  336. package/coverage/src/parsers/rust.ts.html +160 -0
  337. package/coverage/src/parsers/swift.ts.html +169 -0
  338. package/coverage/src/parsers/typescript.ts.html +208 -0
  339. package/coverage/src/parsers/vue.ts.html +322 -0
  340. package/coverage/src/pipeline/cluster-only.ts.html +277 -0
  341. package/coverage/src/pipeline/effort.ts.html +235 -0
  342. package/coverage/src/pipeline/index.html +191 -0
  343. package/coverage/src/pipeline/orchestrator.ts.html +844 -0
  344. package/coverage/src/pipeline/phases/boundary.ts.html +538 -0
  345. package/coverage/src/pipeline/phases/bridge-adapters/electron-ipc.ts.html +358 -0
  346. package/coverage/src/pipeline/phases/bridge-adapters/index.html +176 -0
  347. package/coverage/src/pipeline/phases/bridge-adapters/registry.ts.html +127 -0
  348. package/coverage/src/pipeline/phases/bridge-adapters/tauri.ts.html +394 -0
  349. package/coverage/src/pipeline/phases/bridge-adapters/types.ts.html +178 -0
  350. package/coverage/src/pipeline/phases/bridge-adapters/wails.ts.html +184 -0
  351. package/coverage/src/pipeline/phases/bridge-resolver.ts.html +316 -0
  352. package/coverage/src/pipeline/phases/call-site-extractors.ts.html +592 -0
  353. package/coverage/src/pipeline/phases/communities.ts.html +634 -0
  354. package/coverage/src/pipeline/phases/contextual-proximity.ts.html +349 -0
  355. package/coverage/src/pipeline/phases/cross-file.ts.html +433 -0
  356. package/coverage/src/pipeline/phases/docs-parse.ts.html +1006 -0
  357. package/coverage/src/pipeline/phases/evidence.ts.html +112 -0
  358. package/coverage/src/pipeline/phases/field-access.ts.html +232 -0
  359. package/coverage/src/pipeline/phases/framework-detect.ts.html +412 -0
  360. package/coverage/src/pipeline/phases/god-nodes.ts.html +574 -0
  361. package/coverage/src/pipeline/phases/import-resolver.ts.html +427 -0
  362. package/coverage/src/pipeline/phases/index.html +626 -0
  363. package/coverage/src/pipeline/phases/leiden.ts.html +316 -0
  364. package/coverage/src/pipeline/phases/llm-extract.ts.html +577 -0
  365. package/coverage/src/pipeline/phases/markdown.ts.html +448 -0
  366. package/coverage/src/pipeline/phases/middleware-extractor.ts.html +466 -0
  367. package/coverage/src/pipeline/phases/module-resolution.ts.html +967 -0
  368. package/coverage/src/pipeline/phases/mro.ts.html +253 -0
  369. package/coverage/src/pipeline/phases/orm.ts.html +1594 -0
  370. package/coverage/src/pipeline/phases/parse.ts.html +751 -0
  371. package/coverage/src/pipeline/phases/pdf-parse.ts.html +484 -0
  372. package/coverage/src/pipeline/phases/processes.ts.html +832 -0
  373. package/coverage/src/pipeline/phases/re-export-propagation.ts.html +565 -0
  374. package/coverage/src/pipeline/phases/reachability.ts.html +553 -0
  375. package/coverage/src/pipeline/phases/routes.ts.html +1135 -0
  376. package/coverage/src/pipeline/phases/scan.ts.html +484 -0
  377. package/coverage/src/pipeline/phases/scope-resolution.ts.html +1147 -0
  378. package/coverage/src/pipeline/phases/structure.ts.html +289 -0
  379. package/coverage/src/pipeline/phases/suggest.ts.html +361 -0
  380. package/coverage/src/pipeline/phases/surprises.ts.html +334 -0
  381. package/coverage/src/pipeline/phases/tools.ts.html +625 -0
  382. package/coverage/src/pipeline/phases/variables-phase.ts.html +196 -0
  383. package/coverage/src/pipeline/phases/variables.ts.html +286 -0
  384. package/coverage/src/pipeline/phases/wildcard-phase.ts.html +235 -0
  385. package/coverage/src/pipeline/phases/wildcard-synthesis.ts.html +727 -0
  386. package/coverage/src/pipeline/progress.ts.html +259 -0
  387. package/coverage/src/pipeline/runner.ts.html +469 -0
  388. package/coverage/src/pipeline/types.ts.html +208 -0
  389. package/coverage/src/query/cypher-parser.ts.html +1435 -0
  390. package/coverage/src/query/index.html +116 -0
  391. package/coverage/src/registry/index.html +116 -0
  392. package/coverage/src/registry/repo-registry.ts.html +460 -0
  393. package/coverage/src/regression/baseline-deltas.ts.html +730 -0
  394. package/coverage/src/regression/baseline.ts.html +313 -0
  395. package/coverage/src/regression/counts.ts.html +346 -0
  396. package/coverage/src/regression/index.html +176 -0
  397. package/coverage/src/regression/outcome.ts.html +319 -0
  398. package/coverage/src/regression/tolerance.ts.html +190 -0
  399. package/coverage/src/report/attributed-duplication.ts.html +421 -0
  400. package/coverage/src/report/badge-svg.ts.html +385 -0
  401. package/coverage/src/report/cross-ref-human.ts.html +235 -0
  402. package/coverage/src/report/duplication-grouping.ts.html +307 -0
  403. package/coverage/src/report/grouping.ts.html +496 -0
  404. package/coverage/src/report/human-check.ts.html +958 -0
  405. package/coverage/src/report/human-dupes.ts.html +511 -0
  406. package/coverage/src/report/human-health.ts.html +670 -0
  407. package/coverage/src/report/human.ts.html +445 -0
  408. package/coverage/src/report/index.html +341 -0
  409. package/coverage/src/report/json-actions.ts.html +358 -0
  410. package/coverage/src/report/json-builders.ts.html +295 -0
  411. package/coverage/src/report/json-schema.ts.html +310 -0
  412. package/coverage/src/report/number-format.ts.html +358 -0
  413. package/coverage/src/report/output-grouped.ts.html +391 -0
  414. package/coverage/src/report/pipeline-perf.ts.html +253 -0
  415. package/coverage/src/report/trace-human.ts.html +466 -0
  416. package/coverage/src/reporting/graph-report.ts.html +1378 -0
  417. package/coverage/src/reporting/index.html +116 -0
  418. package/coverage/src/results/fallow-results.ts.html +541 -0
  419. package/coverage/src/results/index.html +131 -0
  420. package/coverage/src/results/types.ts.html +532 -0
  421. package/coverage/src/scope-resolution/evidence-weights.ts.html +208 -0
  422. package/coverage/src/scope-resolution/index.html +116 -0
  423. package/coverage/src/search/ast-chunker.ts.html +703 -0
  424. package/coverage/src/search/diacritic.ts.html +106 -0
  425. package/coverage/src/search/hybrid-query.ts.html +280 -0
  426. package/coverage/src/search/index.html +161 -0
  427. package/coverage/src/search/rrf.ts.html +238 -0
  428. package/coverage/src/security/index.html +131 -0
  429. package/coverage/src/security/safe-fetch.ts.html +424 -0
  430. package/coverage/src/security/sensitive-files.ts.html +157 -0
  431. package/coverage/src/skills/index.html +116 -0
  432. package/coverage/src/skills/platform-skills.ts.html +784 -0
  433. package/coverage/src/staleness/git-staleness.ts.html +283 -0
  434. package/coverage/src/staleness/index.html +116 -0
  435. package/coverage/src/storage/db.ts.html +415 -0
  436. package/coverage/src/storage/edge-store.ts.html +400 -0
  437. package/coverage/src/storage/file-cache.ts.html +319 -0
  438. package/coverage/src/storage/fts-store.ts.html +1240 -0
  439. package/coverage/src/storage/index.html +221 -0
  440. package/coverage/src/storage/node-store.ts.html +712 -0
  441. package/coverage/src/storage/schema.ts.html +598 -0
  442. package/coverage/src/storage/suppressions.ts.html +520 -0
  443. package/coverage/src/storage/unlinked-refs.ts.html +436 -0
  444. package/coverage/src/types.ts.html +676 -0
  445. package/coverage/src/validation/extraction-validator.ts.html +247 -0
  446. package/coverage/src/validation/index.html +116 -0
  447. package/coverage/src/watch/index.html +116 -0
  448. package/coverage/src/watch/watcher.ts.html +499 -0
  449. package/coverage/src/web/analyze-api.ts.html +523 -0
  450. package/coverage/src/web/api.ts.html +1837 -0
  451. package/coverage/src/web/async-jobs.ts.html +412 -0
  452. package/coverage/src/web/index.html +191 -0
  453. package/coverage/src/web/mcp-http.ts.html +766 -0
  454. package/coverage/src/web/react-ui.ts.html +319 -0
  455. package/coverage/src/web/server.ts.html +355 -0
  456. package/coverage/src/wiki/gist-publisher.ts.html +313 -0
  457. package/coverage/src/wiki/index.html +176 -0
  458. package/coverage/src/wiki/prompt-builder.ts.html +190 -0
  459. package/coverage/src/wiki/providers.ts.html +487 -0
  460. package/coverage/src/wiki/wiki-generator.ts.html +736 -0
  461. package/coverage/src/wiki/wiki-store.ts.html +232 -0
  462. package/dist/src/cli/eval-server.d.ts.map +1 -1
  463. package/dist/src/cli/eval-server.js +8 -1
  464. package/dist/src/cli/eval-server.js.map +1 -1
  465. package/dist/src/cli/skill-gen.js.map +1 -1
  466. package/dist/src/graph/regex-search.d.ts.map +1 -1
  467. package/dist/src/graph/regex-search.js +13 -13
  468. package/dist/src/graph/regex-search.js.map +1 -1
  469. package/dist/src/graph/statistics.d.ts +0 -4
  470. package/dist/src/graph/statistics.d.ts.map +1 -1
  471. package/dist/src/graph/statistics.js +0 -7
  472. package/dist/src/graph/statistics.js.map +1 -1
  473. package/dist/src/pipeline/orchestrator.js +22 -0
  474. package/dist/src/pipeline/orchestrator.js.map +1 -1
  475. package/dist/src/pipeline/phases/call-site-extractors.d.ts +8 -0
  476. package/dist/src/pipeline/phases/call-site-extractors.d.ts.map +1 -1
  477. package/dist/src/pipeline/phases/call-site-extractors.js +9 -9
  478. package/dist/src/pipeline/phases/call-site-extractors.js.map +1 -1
  479. package/dist/src/pipeline/phases/module-resolution.js +2 -2
  480. package/dist/src/pipeline/phases/module-resolution.js.map +1 -1
  481. package/dist/src/pipeline/phases/scope-resolution.d.ts.map +1 -1
  482. package/dist/src/pipeline/phases/scope-resolution.js +76 -1
  483. package/dist/src/pipeline/phases/scope-resolution.js.map +1 -1
  484. package/dist/src/registry/repo-registry.d.ts.map +1 -1
  485. package/dist/src/registry/repo-registry.js +1 -2
  486. package/dist/src/registry/repo-registry.js.map +1 -1
  487. package/dist/tsconfig.tsbuildinfo +1 -1
  488. package/package.json +4 -3
  489. package/src/cli/eval-server.ts +8 -1
  490. package/src/cli/skill-gen.ts +16 -16
  491. package/src/graph/regex-search.ts +13 -14
  492. package/src/graph/statistics.ts +0 -8
  493. package/src/pipeline/orchestrator.ts +18 -0
  494. package/src/pipeline/phases/call-site-extractors.ts +17 -9
  495. package/src/pipeline/phases/module-resolution.ts +2 -2
  496. package/src/pipeline/phases/scope-resolution.ts +89 -1
  497. package/src/registry/repo-registry.ts +1 -2
  498. package/vitest.config.ts +7 -0
  499. package/src/analysis/cycles.ts +0 -268
  500. package/src/analysis/trace.ts +0 -300
  501. package/src/analysis/worker-pool.ts +0 -81
  502. package/src/graph/clone-detector.ts +0 -163
  503. package/src/graph/shingle-filter.ts +0 -149
  504. package/src/watch/watch-runner.ts +0 -64
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monograph",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "type": "module",
5
5
  "description": "Native TypeScript code intelligence engine for monomind",
6
6
  "main": "dist/src/index.js",
@@ -20,7 +20,8 @@
20
20
  },
21
21
  "scripts": {
22
22
  "build": "tsc",
23
- "test": "vitest run"
23
+ "test": "vitest run",
24
+ "test:coverage": "vitest run --coverage"
24
25
  },
25
26
  "dependencies": {
26
27
  "better-sqlite3": "^12.0.0",
@@ -56,4 +57,4 @@
56
57
  "typescript": "^7.0.2",
57
58
  "vitest": "^4.1.4"
58
59
  }
59
- }
60
+ }
@@ -9,6 +9,7 @@
9
9
  * createEvalServer('/path/to/repo', 4848)
10
10
  */
11
11
 
12
+ import { createRequire } from 'node:module';
12
13
  import type { Server } from 'http';
13
14
  import type { Application } from 'express';
14
15
  import { openDb, closeDb } from '../storage/db.js';
@@ -49,7 +50,13 @@ export function createEvalServer(repoPath: string, _port?: number): EvalServerHa
49
50
  function getApp(): Application {
50
51
  if (_app) return _app;
51
52
 
52
- // eslint-disable-next-line @typescript-eslint/no-require-imports
53
+ // createRequire, not a bare require(): this package is ESM
54
+ // ("type": "module"), where `require` is undefined at runtime — the
55
+ // eslint-disable that used to sit here silenced the lint but the call
56
+ // still threw "require is not defined" the moment getApp() ran.
57
+ // getApp() is synchronous, so `await import()` is not an option; this is
58
+ // the correct ESM escape hatch for a deliberately deferred load.
59
+ const require = createRequire(import.meta.url);
53
60
  const express = require('express') as typeof import('express');
54
61
  const app = express();
55
62
  app.use(express.json());
@@ -60,29 +60,29 @@ export async function generateSkillFiles(
60
60
  const db = openDb(dbPath);
61
61
 
62
62
  try {
63
- const communities = queryCommunities(db);
63
+ const communities = queryCommunities(db);
64
64
 
65
- if (communities.length === 0) {
66
- return { filesWritten: [], communityCount: 0 };
67
- }
65
+ if (communities.length === 0) {
66
+ return { filesWritten: [], communityCount: 0 };
67
+ }
68
68
 
69
- await fs.mkdir(skillsDir, { recursive: true });
69
+ await fs.mkdir(skillsDir, { recursive: true });
70
70
 
71
- const filesWritten: string[] = [];
71
+ const filesWritten: string[] = [];
72
72
 
73
- for (const community of communities) {
74
- const members = queryMembers(db, community.community_id);
75
- const crossConnections = queryCrossConnections(db, community.community_id);
73
+ for (const community of communities) {
74
+ const members = queryMembers(db, community.community_id);
75
+ const crossConnections = queryCrossConnections(db, community.community_id);
76
76
 
77
- const content = renderSkillMarkdown(community, members, crossConnections, repoPath);
77
+ const content = renderSkillMarkdown(community, members, crossConnections, repoPath);
78
78
 
79
- const kebab = toKebabName(community.label || `community-${community.community_id}`);
80
- const filePath = path.join(skillsDir, `${kebab}.md`);
81
- await fs.writeFile(filePath, content, 'utf-8');
82
- filesWritten.push(filePath);
83
- }
79
+ const kebab = toKebabName(community.label || `community-${community.community_id}`);
80
+ const filePath = path.join(skillsDir, `${kebab}.md`);
81
+ await fs.writeFile(filePath, content, 'utf-8');
82
+ filesWritten.push(filePath);
83
+ }
84
84
 
85
- return { filesWritten, communityCount: communities.length };
85
+ return { filesWritten, communityCount: communities.length };
86
86
  } finally {
87
87
  closeDb(db);
88
88
  }
@@ -48,20 +48,6 @@ export function regexSearchNodes(
48
48
  const results: RegexNodeMatch[] = [];
49
49
 
50
50
  for (const r of rows) {
51
- const node: MonographNode = {
52
- id: r.id,
53
- label: r.label as MonographNode['label'],
54
- name: r.name,
55
- normLabel: r.norm_label,
56
- filePath: r.file_path ?? undefined,
57
- startLine: r.start_line ?? undefined,
58
- endLine: r.end_line ?? undefined,
59
- communityId: r.community_id ?? undefined,
60
- isExported: r.is_exported === 1,
61
- language: r.language ?? undefined,
62
- properties: r.properties ? (JSON.parse(r.properties) as Record<string, unknown>) : undefined,
63
- };
64
-
65
51
  for (const field of fields) {
66
52
  const value =
67
53
  field === 'name' ? r.name :
@@ -70,6 +56,19 @@ export function regexSearchNodes(
70
56
  r.label;
71
57
 
72
58
  if (value && re.test(value)) {
59
+ const node: MonographNode = {
60
+ id: r.id,
61
+ label: r.label as MonographNode['label'],
62
+ name: r.name,
63
+ normLabel: r.norm_label,
64
+ filePath: r.file_path ?? undefined,
65
+ startLine: r.start_line ?? undefined,
66
+ endLine: r.end_line ?? undefined,
67
+ communityId: r.community_id ?? undefined,
68
+ isExported: r.is_exported === 1,
69
+ language: r.language ?? undefined,
70
+ properties: r.properties ? (JSON.parse(r.properties) as Record<string, unknown>) : undefined,
71
+ };
73
72
  results.push({ node, field });
74
73
  break;
75
74
  }
@@ -27,14 +27,6 @@ function getGraph(db: MonographDb): Graph {
27
27
  return graph;
28
28
  }
29
29
 
30
- /**
31
- * Evict the cached graph for a given DB instance (call after writes).
32
- */
33
- export function invalidateGraphCache(db: MonographDb): void {
34
- const key = (db as unknown as { name: string }).name ?? '__default__';
35
- _graphCache.delete(key);
36
- }
37
-
38
30
  /**
39
31
  * Graph density: ratio of actual edges to maximum possible directed edges.
40
32
  * For a directed graph with n nodes: max = n * (n - 1).
@@ -132,6 +132,17 @@ async function buildAsyncLocked(
132
132
 
133
133
  const db = openDb(dbPath);
134
134
 
135
+ // The whole build is one SQL transaction: a phase throwing (e.g. issue
136
+ // #40's FK violation) used to leave whatever earlier phases had already
137
+ // autocommitted sitting in the DB, silently corrupting the index into a
138
+ // stale partial state that a later build wouldn't repair (cache hits skip
139
+ // re-scanning the files that would restore the missing rows). BEGIN/COMMIT/
140
+ // ROLLBACK are issued directly via db.exec() rather than better-sqlite3's
141
+ // `.transaction()` helper, which requires a synchronous callback — the
142
+ // phases below are async. This is still safe: every phase writes through
143
+ // this same single connection, so SQLite serializes them regardless of how
144
+ // the JS event loop interleaves the awaits between phases.
145
+ db.exec('BEGIN');
135
146
  try {
136
147
  const graph = new Graph({ multi: true, type: 'directed' });
137
148
  const ctx: PipelineContext = {
@@ -229,6 +240,13 @@ async function buildAsyncLocked(
229
240
  }
230
241
  }
231
242
  db.prepare("INSERT OR REPLACE INTO index_meta VALUES ('indexed_at', ?)").run(new Date().toISOString());
243
+ db.exec('COMMIT');
244
+ } catch (err) {
245
+ // Best-effort: if the connection is already broken (e.g. the failure was
246
+ // itself a corrupt-database error), rolling back can throw too — the
247
+ // original error is what matters and must not be masked by this one.
248
+ try { db.exec('ROLLBACK'); } catch { /* ignore */ }
249
+ throw err;
232
250
  } finally {
233
251
  closeDb(db);
234
252
  }
@@ -7,6 +7,14 @@ export interface CallSite {
7
7
  form: 'method' | 'direct' | 'dynamic';
8
8
  receiverName?: string;
9
9
  methodName?: string;
10
+ /**
11
+ * Byte offset of the match in the source, used by scope resolution to find
12
+ * the function enclosing this call. Without it every CALLS edge is
13
+ * attributed to the containing File, which makes a function look "used" by
14
+ * its own file just for being declared there — see the dead-code masking
15
+ * described in graph/dead-code.ts.
16
+ */
17
+ offset?: number;
10
18
  }
11
19
 
12
20
  // ── Language keyword sets ────────────────────────────────────────────────────
@@ -71,13 +79,13 @@ function extractSimpleCallSites(
71
79
  const methodPattern = /(\w+)\.(\w+)\s*\(/g;
72
80
  let m: RegExpExecArray | null;
73
81
  while ((m = methodPattern.exec(source)) !== null) {
74
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `${m[1]}.${m[2]}`, form: 'method', receiverName: m[1], methodName: m[2] });
82
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `${m[1]}.${m[2]}`, form: 'method', receiverName: m[1], methodName: m[2] });
75
83
  }
76
84
  const directPattern = new RegExp(`(?<![.[\\w])(${directCharClass})\\s*\\(`, 'g');
77
85
  while ((m = directPattern.exec(source)) !== null) {
78
86
  const name = m[1]!;
79
87
  if (keywords.has(name)) continue;
80
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: name, form: 'direct' });
88
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: name, form: 'direct' });
81
89
  }
82
90
  return sites;
83
91
  }
@@ -112,44 +120,44 @@ export function extractCallSites(
112
120
  const methodPattern = /(\w+)\.(\w+)\s*(?:<[^>]*>\s*)?\(/g;
113
121
  let m: RegExpExecArray | null;
114
122
  while ((m = methodPattern.exec(source)) !== null) {
115
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `${m[1]}.${m[2]}`, form: 'method', receiverName: m[1], methodName: m[2] });
123
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `${m[1]}.${m[2]}`, form: 'method', receiverName: m[1], methodName: m[2] });
116
124
  }
117
125
 
118
126
  const chainedPattern = /[)\]]\s*\.(\w+)\s*(?:<[^>]*>\s*)?\(/g;
119
127
  while ((m = chainedPattern.exec(source)) !== null) {
120
128
  const name = m[1];
121
129
  if (JS_KEYWORDS.has(name)) continue;
122
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `?.${name}`, form: 'method', methodName: name });
130
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `?.${name}`, form: 'method', methodName: name });
123
131
  }
124
132
 
125
133
  const directPattern = /(?<![.[\w])([A-Za-z_$][\w$]*)\s*(?:<[^>]*>\s*)?\(/g;
126
134
  while ((m = directPattern.exec(source)) !== null) {
127
135
  const name = m[1];
128
136
  if (JS_KEYWORDS.has(name)) continue;
129
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: name, form: 'direct', methodName: name });
137
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: name, form: 'direct', methodName: name });
130
138
  }
131
139
 
132
140
  const newPattern = /\bnew\s+([A-Z][\w$]*)\s*(?:<[^>]*>\s*)?\(/g;
133
141
  while ((m = newPattern.exec(source)) !== null) {
134
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `new ${m[1]}`, form: 'direct', methodName: m[1] });
142
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `new ${m[1]}`, form: 'direct', methodName: m[1] });
135
143
  }
136
144
 
137
145
  const dynamicPattern = /\w+\s*\[[\w'"` ]+\]\s*\(/g;
138
146
  while ((m = dynamicPattern.exec(source)) !== null) {
139
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: m[0], form: 'dynamic' });
147
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: m[0], form: 'dynamic' });
140
148
  }
141
149
  } else if (PY_EXTS.has(ext)) {
142
150
  const methodPattern = /(\w+)\.(\w+)\s*\(/g;
143
151
  let m: RegExpExecArray | null;
144
152
  while ((m = methodPattern.exec(source)) !== null) {
145
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `${m[1]}.${m[2]}`, form: 'method', receiverName: m[1], methodName: m[2] });
153
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: `${m[1]}.${m[2]}`, form: 'method', receiverName: m[1], methodName: m[2] });
146
154
  }
147
155
 
148
156
  const directPattern = /(?<![.[\w])([A-Za-z_][\w]*)\s*\(/g;
149
157
  while ((m = directPattern.exec(source)) !== null) {
150
158
  const name = m[1];
151
159
  if (PY_KEYWORDS.has(name)) continue;
152
- sites.push({ callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: name, form: 'direct', methodName: name });
160
+ sites.push({ offset: m.index, callerFileNodeId: fileNodeId, callerFilePath: filePath, calleeRaw: name, form: 'direct', methodName: name });
153
161
  }
154
162
  }
155
163
 
@@ -1,6 +1,6 @@
1
1
  // ── Module resolution for import specifiers ──────────────────────────────────
2
2
 
3
- import { readFileSync, existsSync } from 'fs';
3
+ import { readFileSync, existsSync, readdirSync } from 'fs';
4
4
  import { join, extname, dirname, resolve as resolvePath } from 'path';
5
5
  import type { MonographNode } from '../../types.js';
6
6
  import { TS_JS_EXTS, CJS_MJS_EXTS } from './call-site-extractors.js';
@@ -40,7 +40,7 @@ export function buildWorkspacePackageMap(repoPath: string): Map<string, string>
40
40
  const scanDirs = (base: string, depth: number) => {
41
41
  if (depth > 2) return;
42
42
  let entries: string[];
43
- try { entries = require('fs').readdirSync(base); } catch { return; }
43
+ try { entries = readdirSync(base); } catch { return; }
44
44
  for (const e of entries) {
45
45
  const full = join(base, e);
46
46
  const pkgJson = join(full, 'package.json');
@@ -56,6 +56,86 @@ function buildFunctionIndex(ctx: PipelineContext): {
56
56
  return { byFilePath, nameCounts };
57
57
  }
58
58
 
59
+ /** A callable node with a known line range, used to attribute a call to its caller. */
60
+ interface EnclosingSymbol {
61
+ id: string;
62
+ startLine: number;
63
+ endLine: number;
64
+ }
65
+
66
+ /**
67
+ * Line ranges of every callable, grouped by file, innermost-first.
68
+ *
69
+ * Call edges are attributed to the enclosing function rather than the file.
70
+ * Attributing them to the file makes a function appear "used" by its own file
71
+ * purely because it is declared there, which silently disabled dead-export
72
+ * detection: `detectDeadCodeNodes` rejects any candidate with an inbound CALLS
73
+ * edge, and that self-edge always existed.
74
+ */
75
+ function buildEnclosingIndex(ctx: PipelineContext): Map<string, EnclosingSymbol[]> {
76
+ const byFile = new Map<string, EnclosingSymbol[]>();
77
+ if (!ctx.db) return byFile;
78
+
79
+ const rows = ctx.db
80
+ .prepare(
81
+ `SELECT id, file_path, start_line, end_line FROM nodes
82
+ WHERE label IN ('Function', 'Method', 'Constructor')
83
+ AND file_path IS NOT NULL AND start_line IS NOT NULL AND end_line IS NOT NULL`
84
+ )
85
+ .all() as { id: string; file_path: string; start_line: number; end_line: number }[];
86
+
87
+ for (const row of rows) {
88
+ let list = byFile.get(row.file_path);
89
+ if (!list) { list = []; byFile.set(row.file_path, list); }
90
+ list.push({ id: row.id, startLine: row.start_line, endLine: row.end_line });
91
+ }
92
+
93
+ // Narrowest range first, so the first containing match is the innermost
94
+ // scope — a call inside a closure belongs to the closure, not the function
95
+ // that happens to wrap it.
96
+ for (const list of byFile.values()) {
97
+ list.sort((a, b) => (a.endLine - a.startLine) - (b.endLine - b.startLine));
98
+ }
99
+
100
+ return byFile;
101
+ }
102
+
103
+ /** Line-start offsets, for turning a match offset into a 1-based line number. */
104
+ function buildLineOffsets(source: string): number[] {
105
+ const offsets = [0];
106
+ for (let i = 0; i < source.length; i++) {
107
+ if (source.charCodeAt(i) === 10) offsets.push(i + 1);
108
+ }
109
+ return offsets;
110
+ }
111
+
112
+ function lineAtOffset(lineOffsets: number[], offset: number): number {
113
+ let lo = 0, hi = lineOffsets.length - 1;
114
+ while (lo < hi) {
115
+ const mid = (lo + hi + 1) >> 1;
116
+ if (lineOffsets[mid]! <= offset) lo = mid; else hi = mid - 1;
117
+ }
118
+ return lo + 1;
119
+ }
120
+
121
+ /**
122
+ * The innermost callable containing `offset`, or null when the call sits at
123
+ * module top level — which is genuinely file-scoped, so the file node stays
124
+ * the correct source for those.
125
+ */
126
+ function findEnclosingSymbolId(
127
+ enclosing: EnclosingSymbol[] | undefined,
128
+ lineOffsets: number[],
129
+ offset: number | undefined,
130
+ ): string | null {
131
+ if (!enclosing || enclosing.length === 0 || offset === undefined) return null;
132
+ const line = lineAtOffset(lineOffsets, offset);
133
+ for (const sym of enclosing) {
134
+ if (line >= sym.startLine && line <= sym.endLine) return sym.id;
135
+ }
136
+ return null;
137
+ }
138
+
59
139
  // ── Target resolution ────────────────────────────────────────────────────────
60
140
 
61
141
  function pickBestId(ids: string[], site: CallSite): string | null {
@@ -226,6 +306,7 @@ export const scopeResolutionPhase: PipelinePhase<ScopeResolutionOutput> = {
226
306
 
227
307
  const allImportMaps = buildAllImportMapsFromSource(ctx.repoPath, fileNodesByPath, fileContents);
228
308
  const { byFilePath: fnIndex, nameCounts } = buildFunctionIndex(ctx);
309
+ const enclosingIndex = buildEnclosingIndex(ctx);
229
310
 
230
311
  const edgeStmts = ctx.db ? prepareEdgeStmts(ctx.db) : null;
231
312
  const resolveAllCalls = ctx.db?.transaction(() => {
@@ -243,6 +324,8 @@ export const scopeResolutionPhase: PipelinePhase<ScopeResolutionOutput> = {
243
324
  }
244
325
 
245
326
  const callSites = extractCallSites(source, filePath, fileNode.id, ext);
327
+ const lineOffsets = buildLineOffsets(source);
328
+ const enclosing = enclosingIndex.get(filePath);
246
329
  const importMap = getImportMap(allImportMaps, fileNode.id);
247
330
  const ctorMap = (TS_JS_EXTS.has(ext) || CJS_MJS_EXTS.has(ext)) ? extractConstructorAssignments(source) : undefined;
248
331
  const importedFiles = [...new Set(importMap.values())];
@@ -260,7 +343,12 @@ export const scopeResolutionPhase: PipelinePhase<ScopeResolutionOutput> = {
260
343
  ambiguous++;
261
344
  }
262
345
 
263
- const result = edgeStmts ? emitEdge(edgeStmts, site.callerFileNodeId, resolved.targetId) : 'skipped';
346
+ // Attribute the call to the function it sits in; fall back to the
347
+ // file node for genuine module-top-level calls.
348
+ const sourceId =
349
+ findEnclosingSymbolId(enclosing, lineOffsets, site.offset) ?? site.callerFileNodeId;
350
+
351
+ const result = edgeStmts ? emitEdge(edgeStmts, sourceId, resolved.targetId) : 'skipped';
264
352
  if (result === 'inserted' || result === 'upgraded') {
265
353
  resolvedEdges++;
266
354
  }
@@ -4,7 +4,7 @@
4
4
  * Persists at ~/.monograph/registry.json and tracks all repos indexed by monograph.
5
5
  */
6
6
 
7
- import { mkdirSync, readFileSync, writeFileSync, existsSync } from 'fs';
7
+ import { mkdirSync, readFileSync, writeFileSync, existsSync, renameSync } from 'fs';
8
8
  import { join, basename, dirname } from 'path';
9
9
  import { homedir } from 'os';
10
10
 
@@ -67,7 +67,6 @@ export function saveRegistry(registry: RepoRegistry): void {
67
67
  const tmpPath = registryPath + '.tmp';
68
68
  writeFileSync(tmpPath, JSON.stringify(registry, null, 2), 'utf8');
69
69
  // Rename is atomic on POSIX systems
70
- const { renameSync } = require('fs') as typeof import('fs');
71
70
  renameSync(tmpPath, registryPath);
72
71
  }
73
72
 
package/vitest.config.ts CHANGED
@@ -6,8 +6,15 @@ export default defineConfig({
6
6
  include: ['__tests__/**/*.test.ts', 'src/__tests__/**/*.test.ts'],
7
7
  exclude: ['node_modules', 'dist', '**/._*'],
8
8
  globals: true,
9
+ // Off by default to keep the edit/test loop fast; run
10
+ // `npm run test:coverage` (or pass --coverage) to measure.
9
11
  coverage: {
10
12
  enabled: false,
13
+ provider: 'v8',
14
+ reporter: ['text-summary', 'json-summary', 'html'],
15
+ reportsDirectory: './coverage',
16
+ include: ['src/**/*.ts'],
17
+ exclude: ['src/**/*.test.ts', 'src/__tests__/**', 'src/**/*.d.ts'],
11
18
  },
12
19
  },
13
20
  });