scip-query 0.10.1 → 0.10.2

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 (273) hide show
  1. package/README.md +2 -2
  2. package/dist/augment-vue-worker.js +1 -1
  3. package/dist/{chunk-24PFLKFK.js → chunk-3KLLFNT4.js} +2 -2
  4. package/dist/{chunk-UIWAZ2NT.js → chunk-3UVJJ6Z7.js} +1 -1
  5. package/dist/chunk-3UW7VM4H.js +62 -0
  6. package/dist/chunk-3ZYF3ELZ.js +2 -0
  7. package/dist/{chunk-6YKJSETN.js → chunk-47UA45TU.js} +2 -2
  8. package/dist/{chunk-5VB3WU7K.js → chunk-4ZUJJRWT.js} +2 -2
  9. package/dist/chunk-5B53WB6E.js +4 -0
  10. package/dist/{chunk-LWPEZ4FP.js → chunk-5FOPAXWY.js} +2 -2
  11. package/dist/{chunk-CCB45WDY.js → chunk-5M4TYWVI.js} +2 -2
  12. package/dist/{chunk-PV4CEDIL.js → chunk-5QJXH6ZL.js} +5 -5
  13. package/dist/{chunk-NN3O7TPH.js → chunk-64MNV6AB.js} +1 -1
  14. package/dist/{chunk-LWWZBABT.js → chunk-77YBOOYT.js} +2 -2
  15. package/dist/chunk-7KCSELEV.js +2 -0
  16. package/dist/{chunk-GZXXBDJA.js → chunk-7OHWPJ5N.js} +2 -2
  17. package/dist/{chunk-BJ7OHKB5.js → chunk-7S5E7KWT.js} +1 -1
  18. package/dist/chunk-A3VNUGKJ.js +2 -0
  19. package/dist/{chunk-CMGOXDVP.js → chunk-A4L36SZS.js} +2 -2
  20. package/dist/{chunk-5D3BT4B4.js → chunk-AUVBR62P.js} +2 -2
  21. package/dist/chunk-AW4N6MGC.js +18 -0
  22. package/dist/{chunk-65UWNXEH.js → chunk-B6MJ5VQV.js} +2 -2
  23. package/dist/chunk-BKDXBJDQ.js +2 -0
  24. package/dist/{chunk-WZVTADY7.js → chunk-C2QSK7E7.js} +1 -1
  25. package/dist/chunk-C3MZZ2ZN.js +2 -0
  26. package/dist/{chunk-GTNPPGZJ.js → chunk-CAWSSEVM.js} +2 -2
  27. package/dist/chunk-CFL2CNIF.js +10 -0
  28. package/dist/{chunk-E55WCTLH.js → chunk-CJJP64OC.js} +2 -2
  29. package/dist/chunk-CNTEQMHA.js +2 -0
  30. package/dist/{chunk-ADKQX2OY.js → chunk-CRU42NJU.js} +2 -2
  31. package/dist/chunk-CSWZFD46.js +2 -0
  32. package/dist/{chunk-QOFKVNFE.js → chunk-CTCAF3YA.js} +2 -2
  33. package/dist/{chunk-YVQUQIBM.js → chunk-D322LMSA.js} +2 -2
  34. package/dist/{chunk-IJYWCB57.js → chunk-DAI74TJU.js} +2 -2
  35. package/dist/chunk-DE7MA6OD.js +3 -0
  36. package/dist/chunk-DJMK4DBL.js +2 -0
  37. package/dist/chunk-DRAZH77R.js +7 -0
  38. package/dist/{chunk-FVX4GEAC.js → chunk-E44ZMVNA.js} +2 -2
  39. package/dist/{chunk-MESUJJVQ.js → chunk-E7KERP7E.js} +2 -2
  40. package/dist/{chunk-YIE5FZAF.js → chunk-EOZIZWW4.js} +2 -2
  41. package/dist/{chunk-XGGTESMN.js → chunk-ERHOS6AW.js} +2 -2
  42. package/dist/{chunk-5HDYAOSF.js → chunk-ESG4HBEF.js} +2 -2
  43. package/dist/{chunk-HCQ7J2N5.js → chunk-EWC3UK4V.js} +3 -3
  44. package/dist/chunk-FGCL6NDB.js +8 -0
  45. package/dist/chunk-FIB4JPEX.js +2 -0
  46. package/dist/chunk-FNRPGGVI.js +2 -0
  47. package/dist/{chunk-QUKZ77A6.js → chunk-FOQHUKNZ.js} +2 -2
  48. package/dist/chunk-FPMVCDIJ.js +2 -0
  49. package/dist/{chunk-QH5GTVVB.js → chunk-FUPDW5AC.js} +2 -2
  50. package/dist/{chunk-B3HMRQDA.js → chunk-G3WGZU5Q.js} +2 -2
  51. package/dist/{chunk-TUAPDKBI.js → chunk-GS33KGAY.js} +2 -2
  52. package/dist/{chunk-623UQCVG.js → chunk-GZCQTZLK.js} +2 -2
  53. package/dist/{chunk-SA6B3EGD.js → chunk-HVTYSC26.js} +2 -2
  54. package/dist/{chunk-R7S3UCDR.js → chunk-ICXVNWMI.js} +2 -2
  55. package/dist/chunk-JM72FNGA.js +2 -0
  56. package/dist/{chunk-DRU74YUM.js → chunk-KPHKX4LP.js} +1 -1
  57. package/dist/{chunk-YYCQQBMG.js → chunk-LPLGJ4HO.js} +2 -2
  58. package/dist/chunk-MHK7Z53U.js +2 -0
  59. package/dist/chunk-MHTDOFV7.js +5 -0
  60. package/dist/chunk-MUULWXSJ.js +2 -0
  61. package/dist/chunk-MZ7APUFN.js +3 -0
  62. package/dist/{chunk-LYS4SMAQ.js → chunk-NNDYO2DX.js} +2 -2
  63. package/dist/{chunk-ATGRITZP.js → chunk-NP5HYVLX.js} +4 -4
  64. package/dist/{chunk-MHAQXOZY.js → chunk-NVFERV4U.js} +2 -2
  65. package/dist/{chunk-LWYIGRHR.js → chunk-NXIAHE7F.js} +1 -1
  66. package/dist/chunk-O3OKSF6O.js +2 -0
  67. package/dist/chunk-O4L4AB3T.js +2 -0
  68. package/dist/{chunk-TMS4JPWY.js → chunk-OBBDKQAG.js} +2 -2
  69. package/dist/chunk-OLD6PBU6.js +7 -0
  70. package/dist/{chunk-5BZOSICN.js → chunk-PFOCOG57.js} +1 -1
  71. package/dist/{chunk-CFLYMEUS.js → chunk-PVZMPG5I.js} +1 -1
  72. package/dist/{chunk-T67R7V5I.js → chunk-QLNGUWR7.js} +2 -2
  73. package/dist/chunk-QSXQT3NE.js +2 -0
  74. package/dist/{chunk-6TWFT4Y5.js → chunk-QVCCLDZI.js} +2 -2
  75. package/dist/{chunk-PNN3D4BE.js → chunk-RHTJBYZ5.js} +2 -2
  76. package/dist/chunk-SPE4YCOT.js +7 -0
  77. package/dist/{chunk-4N7LFYSD.js → chunk-TM6GVHA6.js} +2 -2
  78. package/dist/chunk-TO54DY4O.js +2 -0
  79. package/dist/{chunk-HQHFMPLJ.js → chunk-UMNENNTX.js} +2 -2
  80. package/dist/chunk-UNJG7P2I.js +2 -0
  81. package/dist/{chunk-TKDJQ2WD.js → chunk-UUBMFL3F.js} +1 -1
  82. package/dist/chunk-VAA5FFIW.js +2 -0
  83. package/dist/chunk-WDUTG2ZR.js +4 -0
  84. package/dist/chunk-X7ZY6FFF.js +4 -0
  85. package/dist/{chunk-RNLUCQJB.js → chunk-YQH353VA.js} +2 -2
  86. package/dist/{chunk-44JOJLMO.js → chunk-YTR4CO5S.js} +2 -2
  87. package/dist/chunk-YUOAAR24.js +2 -0
  88. package/dist/{chunk-ADTG377O.js → chunk-YYD245WG.js} +2 -2
  89. package/dist/{chunk-I6PTB2CM.js → chunk-Z4VHYJ5U.js} +2 -2
  90. package/dist/chunk-ZFMPHDAT.js +4 -0
  91. package/dist/chunk-ZQLO2SCU.js +6 -0
  92. package/dist/chunk-ZSLT7NWQ.js +61 -0
  93. package/dist/cli.js +242 -225
  94. package/dist/{config-types-Bok4jrO3.d.ts → config-types-Bj4sh28g.d.ts} +8 -0
  95. package/dist/{db-BkFlkzI3.d.ts → db-CTarohbZ.d.ts} +1 -1
  96. package/dist/git-history-Dao3_Pu9.d.ts +12 -0
  97. package/dist/{health-CbGMdRPg.d.ts → health-Bx0x1HAG.d.ts} +23 -2
  98. package/dist/index.d.ts +3 -3
  99. package/dist/index.js +1 -1
  100. package/dist/postinstall.js +1 -1
  101. package/dist/queries/affected.d.ts +2 -2
  102. package/dist/queries/affected.js +1 -1
  103. package/dist/queries/bottlenecks.d.ts +6 -2
  104. package/dist/queries/bottlenecks.js +1 -1
  105. package/dist/queries/by-kind.d.ts +2 -2
  106. package/dist/queries/by-kind.js +1 -1
  107. package/dist/queries/call-graph.d.ts +2 -2
  108. package/dist/queries/call-graph.js +1 -1
  109. package/dist/queries/change-surface.d.ts +2 -2
  110. package/dist/queries/change-surface.js +1 -1
  111. package/dist/queries/cleanup-plan.d.ts +2 -2
  112. package/dist/queries/cleanup-plan.js +1 -1
  113. package/dist/queries/co-change.d.ts +37 -3
  114. package/dist/queries/co-change.js +1 -1
  115. package/dist/queries/code.d.ts +2 -2
  116. package/dist/queries/code.js +1 -1
  117. package/dist/queries/complexity-hotspots.d.ts +2 -2
  118. package/dist/queries/complexity-hotspots.js +1 -1
  119. package/dist/queries/complexity.d.ts +2 -2
  120. package/dist/queries/complexity.js +1 -1
  121. package/dist/queries/convergence.d.ts +2 -2
  122. package/dist/queries/convergence.js +1 -1
  123. package/dist/queries/coupling.d.ts +6 -2
  124. package/dist/queries/coupling.js +1 -1
  125. package/dist/queries/cycles.d.ts +2 -2
  126. package/dist/queries/cycles.js +1 -1
  127. package/dist/queries/dataflow.d.ts +2 -2
  128. package/dist/queries/dataflow.js +1 -1
  129. package/dist/queries/dead.d.ts +10 -3
  130. package/dist/queries/dead.js +1 -1
  131. package/dist/queries/deep-chains.d.ts +6 -2
  132. package/dist/queries/deep-chains.js +1 -1
  133. package/dist/queries/deps.d.ts +2 -2
  134. package/dist/queries/deps.js +1 -1
  135. package/dist/queries/diff-gate.d.ts +48 -3
  136. package/dist/queries/diff-gate.js +1 -1
  137. package/dist/queries/diff-impact.d.ts +2 -2
  138. package/dist/queries/diff-impact.js +1 -1
  139. package/dist/queries/doc-drift.d.ts +20 -3
  140. package/dist/queries/doc-drift.js +1 -1
  141. package/dist/queries/drift.d.ts +10 -3
  142. package/dist/queries/drift.js +1 -1
  143. package/dist/queries/extract-candidates.d.ts +11 -3
  144. package/dist/queries/extract-candidates.js +1 -1
  145. package/dist/queries/fan.d.ts +2 -2
  146. package/dist/queries/fan.js +1 -1
  147. package/dist/queries/files.d.ts +2 -2
  148. package/dist/queries/files.js +1 -1
  149. package/dist/queries/health.d.ts +3 -3
  150. package/dist/queries/health.js +1 -1
  151. package/dist/queries/hierarchy.d.ts +2 -2
  152. package/dist/queries/hierarchy.js +1 -1
  153. package/dist/queries/hotspots.d.ts +2 -2
  154. package/dist/queries/hotspots.js +1 -1
  155. package/dist/queries/imports.d.ts +2 -2
  156. package/dist/queries/imports.js +1 -1
  157. package/dist/queries/incomplete-migration.d.ts +14 -3
  158. package/dist/queries/incomplete-migration.js +1 -1
  159. package/dist/queries/index.d.ts +17 -15
  160. package/dist/queries/index.js +1 -1
  161. package/dist/queries/isolated.d.ts +2 -2
  162. package/dist/queries/isolated.js +1 -1
  163. package/dist/queries/locality-candidates.d.ts +51 -0
  164. package/dist/queries/locality-candidates.js +2 -0
  165. package/dist/queries/members.d.ts +2 -2
  166. package/dist/queries/members.js +1 -1
  167. package/dist/queries/methods.d.ts +2 -2
  168. package/dist/queries/methods.js +1 -1
  169. package/dist/queries/outline.d.ts +2 -2
  170. package/dist/queries/outline.js +1 -1
  171. package/dist/queries/passthrough-candidates.d.ts +8 -3
  172. package/dist/queries/passthrough-candidates.js +1 -1
  173. package/dist/queries/plan-context.d.ts +4 -2
  174. package/dist/queries/plan-context.js +1 -1
  175. package/dist/queries/react-component-duplicates.d.ts +2 -2
  176. package/dist/queries/react-component-duplicates.js +1 -1
  177. package/dist/queries/react-hook-candidates.d.ts +9 -3
  178. package/dist/queries/react-hook-candidates.js +1 -1
  179. package/dist/queries/react-large-component-pressure.d.ts +9 -3
  180. package/dist/queries/react-large-component-pressure.js +1 -1
  181. package/dist/queries/recent-duplicates.d.ts +25 -3
  182. package/dist/queries/recent-duplicates.js +1 -1
  183. package/dist/queries/redundant-reexports.d.ts +7 -3
  184. package/dist/queries/redundant-reexports.js +1 -1
  185. package/dist/queries/refs.d.ts +2 -2
  186. package/dist/queries/refs.js +1 -1
  187. package/dist/queries/self-audit.d.ts +2 -2
  188. package/dist/queries/self-audit.js +1 -1
  189. package/dist/queries/similar-chains.d.ts +2 -2
  190. package/dist/queries/similar-chains.js +1 -1
  191. package/dist/queries/similar-files.d.ts +2 -2
  192. package/dist/queries/similar-files.js +1 -1
  193. package/dist/queries/similar-signatures.d.ts +2 -2
  194. package/dist/queries/similar-signatures.js +1 -1
  195. package/dist/queries/similar.d.ts +16 -3
  196. package/dist/queries/similar.js +1 -1
  197. package/dist/queries/slice.d.ts +2 -2
  198. package/dist/queries/slice.js +1 -1
  199. package/dist/queries/stale-abstractions.d.ts +10 -3
  200. package/dist/queries/stale-abstractions.js +1 -1
  201. package/dist/queries/stats.d.ts +2 -2
  202. package/dist/queries/stats.js +1 -1
  203. package/dist/queries/surface.d.ts +2 -2
  204. package/dist/queries/surface.js +1 -1
  205. package/dist/queries/symbols.d.ts +2 -2
  206. package/dist/queries/symbols.js +1 -1
  207. package/dist/queries/system.d.ts +2 -2
  208. package/dist/queries/system.js +1 -1
  209. package/dist/queries/trace.d.ts +2 -2
  210. package/dist/queries/trace.js +1 -1
  211. package/dist/queries/unused-imports.d.ts +4 -0
  212. package/dist/queries/unused-imports.js +2 -0
  213. package/dist/queries/unused-params.d.ts +2 -2
  214. package/dist/queries/unused-params.js +1 -1
  215. package/dist/queries/vue-component-duplicates.d.ts +2 -2
  216. package/dist/queries/vue-component-duplicates.js +1 -1
  217. package/dist/queries/vue-composable-candidates.d.ts +9 -3
  218. package/dist/queries/vue-composable-candidates.js +1 -1
  219. package/dist/queries/vue-large-view-pressure.d.ts +9 -3
  220. package/dist/queries/vue-large-view-pressure.js +1 -1
  221. package/dist/queries/wrapper-candidates.d.ts +6 -3
  222. package/dist/queries/wrapper-candidates.js +1 -1
  223. package/dist/reindex-worker.js +1 -1
  224. package/dist/reindex.d.ts +1 -1
  225. package/dist/reindex.js +1 -1
  226. package/dist/runtime.d.ts +1 -1
  227. package/dist/runtime.js +2 -2
  228. package/docs/COMMAND_REFERENCE.md +3 -2
  229. package/docs/analyzer-inventory.md +162 -0
  230. package/docs/analyzer-validation-ledger.md +262 -0
  231. package/docs/analyzer-validation-protocol.md +192 -0
  232. package/docs/locality-analyzer-design.md +193 -0
  233. package/package.json +14 -3
  234. package/skills/scip-directory-architecture/SKILL.md +178 -0
  235. package/skills/scip-maintainability/SKILL.md +1 -1
  236. package/skills/scip-query/SKILL.md +2 -1
  237. package/skills/scip-query-setup/SKILL.md +118 -0
  238. package/skills/scip-react-maintainability/SKILL.md +1 -1
  239. package/skills/scip-vue-maintainability/SKILL.md +1 -1
  240. package/dist/chunk-23FVN4Y5.js +0 -2
  241. package/dist/chunk-27KPKLRJ.js +0 -7
  242. package/dist/chunk-2NLK4INB.js +0 -2
  243. package/dist/chunk-2XKAMW6B.js +0 -61
  244. package/dist/chunk-332L7SRO.js +0 -2
  245. package/dist/chunk-4EAANIWC.js +0 -2
  246. package/dist/chunk-5ALI77D7.js +0 -3
  247. package/dist/chunk-5IDEQEM4.js +0 -4
  248. package/dist/chunk-62NMBOA5.js +0 -2
  249. package/dist/chunk-64LH2QUP.js +0 -62
  250. package/dist/chunk-6U4EODW3.js +0 -2
  251. package/dist/chunk-A2GVUCZR.js +0 -8
  252. package/dist/chunk-DBIG4QAJ.js +0 -2
  253. package/dist/chunk-DMLPJ75B.js +0 -2
  254. package/dist/chunk-DTERBKUE.js +0 -7
  255. package/dist/chunk-F4PKYBQB.js +0 -2
  256. package/dist/chunk-JTRY2YRJ.js +0 -2
  257. package/dist/chunk-L77GXANO.js +0 -6
  258. package/dist/chunk-LT6GJ27X.js +0 -10
  259. package/dist/chunk-LUBKUISI.js +0 -2
  260. package/dist/chunk-LVYXX7ZW.js +0 -2
  261. package/dist/chunk-LXM7AHQG.js +0 -4
  262. package/dist/chunk-LY6NRJPJ.js +0 -2
  263. package/dist/chunk-N2T2GPYQ.js +0 -2
  264. package/dist/chunk-OB6PEVI3.js +0 -2
  265. package/dist/chunk-R42LZMLX.js +0 -2
  266. package/dist/chunk-RGDUIMNE.js +0 -3
  267. package/dist/chunk-RYBMW2EN.js +0 -2
  268. package/dist/chunk-TTGWDUJ4.js +0 -5
  269. package/dist/chunk-UVK3SL4Z.js +0 -2
  270. package/dist/chunk-W3PQRAI4.js +0 -2
  271. package/dist/chunk-WWFBDM5Y.js +0 -2
  272. package/dist/chunk-Y33GRQK6.js +0 -18
  273. package/dist/chunk-YISMWW66.js +0 -7
@@ -0,0 +1,192 @@
1
+ # Analyzer Validation Protocol
2
+
3
+ This document answers the part of the analyzer review that the inventory does not: how to test whether each analyzer is right across real codebases, how to label false positives and false negatives, and how to turn those labels into programmatic precision work.
4
+
5
+ The companion inventory is `docs/analyzer-inventory.md`. The running work tracker is `docs/analyzer-validation-ledger.md`. The companion placement design is `docs/locality-analyzer-design.md`.
6
+
7
+ ## Core Concepts
8
+
9
+ A validation corpus is a deliberately chosen set of real repositories, revisions, and stack shapes used to test analyzer claims against maintained code. It is not just a pile of projects; its essential job is to expose each analyzer to the kinds of source layouts, framework idioms, build boundaries, and historical changes that determine whether the analyzer's claim would matter to a maintainer.
10
+
11
+ An analyzer verdict is a human-reviewed classification of one analyzer output or one known missed case. It ties the tool's structured claim back to source files, references, git history, and product structure so the claim can be counted as true, false, accepted-by-design, or still undecidable.
12
+
13
+ A true positive is an analyzer claim where the reported code location really does have the maintenance problem the analyzer names, and the next reasonable maintainer action matches the analyzer's suggested direction.
14
+
15
+ A false positive is an analyzer claim where the reported evidence exists but the inspected code shows that no repair is warranted. The usual cause is that the analyzer noticed a real structural pattern but missed ownership, framework convention, product meaning, or intentional API design.
16
+
17
+ A false negative is an existing maintenance problem that the analyzer's stated scope should have reported but did not. It matters more than an empty report because it shows a missing detector feature, missing language support, skipped source unit, or threshold that is too narrow.
18
+
19
+ An accepted design is a reported pattern that is real but intentionally kept. It should not be counted as a bug in the codebase; it is feedback that the analyzer needs either suppression support, a lower score weight, or a better explanation field.
20
+
21
+ Programmatic precision work is a code change to the analyzer, its evidence model, or its score model that makes future reports closer to maintainer judgment without hard-coding one repository. It is different from tuning a threshold until one known example disappears.
22
+
23
+ ## Validation Corpus
24
+
25
+ The first corpus should use local repositories that are already available and large enough to stress the current analyzer families.
26
+
27
+ | Repository | Stack shape | Source evidence seen locally | Analyzer coverage |
28
+ | ------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------- |
29
+ | `/Users/aydansalois/Documents/GitHub/scip-query` | TypeScript CLI and analysis library | 290 `.ts`, 103 `.md` | Core graph, cleanup, health, docs, diff gate, score behavior |
30
+ | `/Users/aydansalois/Documents/GitHub/Stable_Management` | npm workspaces with Vue frontend, TypeScript backend, shared package | 1,168 `.ts`, 409 `.vue`, 380 `.md` | Vue analyzers, co-change, cross-workspace coupling, docs, large-index budget |
31
+ | `/Users/aydansalois/Documents/GitHub/Vega_2.0` | TypeScript monorepo with React web app, API app, shared packages | 1,567 `.ts`, 672 `.tsx`, 1,163 `.md` | React analyzers, monorepo locality, diff gate, shared-package coupling |
32
+ | `/Users/aydansalois/Documents/GitHub/SynthRunnerRust` | Rust project | 27 `.rs`, 36 `.md` | SCIP graph smoke coverage, non-TypeScript command behavior, docs and git-history signals |
33
+
34
+ The current best field-test evidence is Stable_Management. A previous run found 1,167 indexed files, 93k symbols, 491 commits analyzed, useful co-change clusters, a bounded `health` score of 91, and 155 baseline findings. It also reported an honest negative: candidate-style findings did not currently predict fix commits well, with validation ratios of 0.6x on Stable_Management and 0.36x on scip-query.
35
+
36
+ That negative is part of the protocol. It means candidate analyzers can be useful without being predictive enough to deserve the same score weight as direct repair analyzers.
37
+
38
+ ## Run Protocol
39
+
40
+ For each repository, record the exact revision first.
41
+
42
+ ```sh
43
+ git -C /path/to/repo rev-parse HEAD
44
+ ```
45
+
46
+ Then index and capture the broad report.
47
+
48
+ ```sh
49
+ cd /path/to/repo
50
+ scip-query reindex
51
+ scip-query health --full --json > /tmp/scip-query-validation/REPO/health.json
52
+ scip-query diff-gate --json > /tmp/scip-query-validation/REPO/diff-gate.json
53
+ ```
54
+
55
+ For each analyzer under review, capture three samples when possible.
56
+
57
+ | Sample | What to inspect | Why it exists |
58
+ | -------------------- | ------------------------------------------------------ | --------------------------------------------------------------- |
59
+ | Top findings | 10 highest-ranked findings | Tests whether ranking puts obvious work first |
60
+ | Threshold edge | 5 findings near the default threshold or last page | Tests whether cutoffs are calibrated |
61
+ | Expected-miss probes | 5 known cases from code search, history, or user notes | Tests false negatives instead of only checking emitted findings |
62
+
63
+ Every sampled finding should be reviewed with the same evidence bundle:
64
+
65
+ ```sh
66
+ scip-query plan-context <symbol-or-file> --full --json
67
+ scip-query refs <symbol> --json
68
+ scip-query code <symbol> --json
69
+ git log --oneline -- <file>
70
+ ```
71
+
72
+ For file-level or history-level analyzers, substitute the file tools:
73
+
74
+ ```sh
75
+ scip-query change-surface <file> --full --json
76
+ scip-query imports <file> --json
77
+ scip-query deps <file> --json
78
+ scip-query rdeps <file> --json
79
+ scip-query co-change <file> --full --json
80
+ ```
81
+
82
+ The validation record should be small enough to write for every sampled result.
83
+
84
+ ```json
85
+ {
86
+ "repo": "Stable_Management",
87
+ "revision": "COMMIT",
88
+ "command": "vue-composable-candidates",
89
+ "findingId": "stable identifier or pasted summary",
90
+ "location": "frontend/src/views/Example.vue",
91
+ "verdict": "tp | fp | accepted_design | needs_judgment | fn",
92
+ "actionTier": "direct | signal | support",
93
+ "evidence": ["source/reference/history facts that make the verdict reproducible"],
94
+ "counterevidence": ["facts that weaken the analyzer claim"],
95
+ "precisionWork": "threshold, parser, evidence field, skip rule, score weight, wording, or none"
96
+ }
97
+ ```
98
+
99
+ Do not accept a precision change unless it survives at least one second repository or one focused fixture. That is the guard against fitting the analyzer to whichever repo annoyed us today.
100
+
101
+ ## Analyzer Matrix
102
+
103
+ | Analyzer or family | True-positive standard | Likely false positives | False-negative probes | Programmatic precision work |
104
+ | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
105
+ | `cleanup-plan` | The batch deletes graph-unreferenced production code and `--verify` keeps the checker green. | Entry points, reflection, generated exports, CLI/plugin surfaces, unrecognized framework-discovered files. | Search for manually deleted dead code in recent history and compare with prior report. | Better root-surface detection, package export reading, framework-discovered route/page exports, and verification summaries are implemented; generated/reflection root coverage remains a future caveat. |
106
+ | `dead`, `new-dead`, `isolated` | The symbol has no real production consumers and is not an entry surface. | File-private helpers, test-only helpers, exported APIs consumed outside the index, generated or reflection entry points. | Known orphan functions found by `rg`, deleted symbols in git history, test fixtures with dynamic usage. | Separate "dead" from "file-internal", package/export metadata, and framework-discovered route/page roots are implemented; generated/reflection roots and external consumer evidence remain future caveats. |
107
+ | `unused-params` | A trailing simple parameter is unused in all relevant implementations and can be removed without API breakage. | Interface conformance, callback arity, overload compatibility, framework signatures, future public API shape. | Search for underscore-less trailing params in changed files and compare with command output. | Type-aware override/interface checks, callback convention allowlists, public API guards. |
108
+ | `unused-imports`, `drift` unused-import findings | The imported binding is never referenced in the file's executable or type surface. | Type-only imports hidden by parser limits, macro usage, framework compiler usage, generated symbols. | Compare against TypeScript/ESLint unused import diagnostics where available. | Compiler-oracle comparison, macro/framework allowlists, unused-import evidence in output. |
109
+ | `redundant-reexports` | A private barrel re-export has zero barrel consumers, zero direct consumers, and emits `actionTier: "direct"`. | Public package API, external consumers outside the repo, documentation examples, generated SDK boundaries. | Inspect barrels with no internal imports and compare against package exports/docs. | Package `exports`, directory index entrypoints, nested package manifests, action tier, surface evidence, and recommendations are now emitted; generated-surface caveats remain future precision work. |
110
+ | `passthrough-candidates` | The function only forwards arguments to one callee, adds no stable name, policy, boundary, public-facade role, or adaptation, and the emitted `actionTier` is `direct`. | Domain vocabulary wrappers, API adapters, test seams, telemetry/auth wrappers, public facade names, package-public exports, service/provider boundaries, capability modules, access-policy forwarding. | Search for tiny wrappers around known callees that command misses. | Action tier, runtime-boundary evidence, separate public-facade evidence, recommendation, and health score discount are now emitted; clean Vega second-corpus confirmation kept signal/direct counts stable. |
111
+ | `wrapper-candidates` | A small one-consumer wrapper adds no useful concept and can be inlined. | Boundary naming, dependency inversion, future API shape, test isolation, schema/contract modules. | Inspect one-consumer helpers in high-churn files. | Consumer-kind evidence, caller fan-in smoothing, naming/domain hints, suppression-informed weight reduction. |
112
+ | `stale-abstractions` | A type/class/helper has zero consumers or one accidental consumer and no boundary role, and the emitted staleness kind/action tier correctly separates unused cleanup from one-consumer ownership review. | Contract types, generated schema types, nominal domain names, low-consumer but intentionally public API. | Search for old low-consumer files, compare with command and suppressions. | Action tier, staleness kind, and recommendation are now emitted; one-consumer rows stay contextual/support in score calibration unless stronger public-surface evidence changes the claim. |
113
+ | `similar`, `similar-files`, `similar-chains`, `similar-signatures`, `convergence` | Two units share enough behavior or dependency shape that unification would reduce real duplication. | Coincidental same framework plumbing, shared type shape but different concepts, generated code, parallel product flows, or cross-language structural overlap without recognized semantic tokens. | Manually inspect known copy-paste pairs, recent duplicated commits, and repeated command handlers. | Domain-token reporting, framework-token downweighting, neutral `structural-overlap` evidence, changed-code directionality, grouped evidence rather than scalar similarity alone. |
114
+ | `recent-duplicates`, diff-gate `echo` | New or recently changed code re-implements older code with the same behavior. | Boilerplate repeated by framework convention, tests, intentionally forked product variants. | Scan recent commits for "copy", "duplicate", "refactor", or similar edits not reported. | Root-cause groups now separate review items from pairwise evidence; age windows, test/generated filters, behavior-token evidence, and established-owner links remain future precision candidates. |
115
+ | `extract-candidates` | A large callable contains a cohesive callee cluster, and the emitted extraction kind/recommendation correctly frames it as workflow orchestration, a broad helper cluster, or a cohesive helper cluster. | Incidental call clustering, readable local sequence, algorithm steps that should stay together, or helper groups without a stable concept name. | Inspect large functions with obvious sections and compare with report. | Extraction kind, action tier, reasons, and recommendation are now emitted; locality and score calibration are recorded, while placement decisions remain report-only through the locality workflow. |
116
+ | `incomplete-migration` | A new helper is used at some matching sites while other equivalent sites still contain the old inline pattern, and the old site passes both helper-containment and site-coverage checks. | Intentional partial rollout, tests documenting old behavior, helper only valid for one subtype, or broad orchestration sites where the helper pattern is only a small fragment. | Search diffs with new helpers and repeated old call clusters. | Two-sided containment, helper shape, site coverage, broad-site regression coverage, migration-scope hints, and second-corpus same-scope validation are now recorded. |
117
+ | `react-component-duplicates`, `vue-component-duplicates` | Two components repeat substantial render structure where a component extraction would preserve product meaning. | Design-system repetition, route-specific layouts, data-table boilerplate, static labels inflating similarity. | Inspect similar screenshots/templates not reported, especially after large component splits. | Framework-token downweighting, static text handling, shared component/import evidence, route/domain context. |
118
+ | `react-hook-candidates`, `vue-composable-candidates` | Components repeat state, effects, lifecycle, request, or handler behavior that can live in a hook/composable, and the row's evidence class points to domain or mixed behavior rather than only generic workflow. | Generic useState/useEffect/useQuery plumbing, unrelated screens using the same framework primitives, or existing shared abstractions that already own the workflow. | Search for repeated custom hook/composable calls and copied handler names. | Evidence class and action tier are now emitted; field validation and score calibration are recorded, and new non-empty corpora can extend calibration later. |
119
+ | `react-large-component-pressure`, `vue-large-view-pressure` | A component/view is large enough that unrelated reasons to change are forced through one file. | Generated views, story/demo files, intentionally monolithic route shells, style-heavy one-off pages. | Search largest React/Vue files and compare with command output. | Pressure-kind/context recommendations are validated; future locality recommendations remain report-only until consumer coverage improves. |
120
+ | `complexity`, `complexity-hotspots` | A symbol or file has enough branching, LOC, fan-in, or fan-out that local reasoning and change risk are objectively high. | Central orchestration code, parsers, reducers, generated code, tables expressed as code. | Compare against high-branch files from code search and known bug-fix hotspots. | Keep cyclomatic and graph-pressure scores separate, report branch evidence, combine with churn/fix density. |
121
+ | `cycles` | A real dependency cycle crosses source files in a way that makes layering or change order harder. | Barrel cycles, test cycles, module-hierarchy cycles, framework registration loops. | Compare file dependency SCCs with `deps`/`rdeps`, seed fixture cycles. | Keep existing cycle-kind split, score only real cycles, improve barrel/test classification. |
122
+ | `co-change`, diff-gate `co-change-partner` | Files repeatedly change together without a dependency edge, showing hidden coordination work; partner class, commit scope, recency, and commit-subject context now distinguish focused current pairs from broad, stale, unlabeled, fix-labeled, or docs-labeled history. | Same feature touched by broad commits, stale coupling that history no longer predicts, local commit subjects that do not reflect true tracker labels, or a partner class that is real but does not imply this diff needs the other side. | Inspect known schema/client, env/config, doc/code pairs and changed partner misses. | Partner-class evidence, declared-coupling suggestions, broad-sweep context, recency context, local subject labels, issue refs, external-label-unavailable status, and health score weighting are now emitted; continue only with future metadata-provider validation for true issue/PR labels. |
123
+ | `doc-drift`, diff-gate `doc-reference` | A doc cites code that moved, broke, or kept changing after the doc claim stopped changing, and the cited claim or doc intent indicates whether this is current guidance, support evidence, or a broken reference. | Exploratory docs, historical notes, configuration examples, docs intentionally describing old behavior. | Search docs with path references and compare broken/stale outputs. | Cited-claim metadata, citation-kind output, co-change-only historical-note intent, Markdown-local citation parsing, and second-corpus parser validation are now recorded. |
124
+ | `drift` layer and pattern findings | Imports violate an explicit or strongly inferred local architecture rule, and the row's action tier correctly separates explicit policy from inferred signal. | Inferred rules from too few siblings, migration states, intentionally exceptional bridge files. | Inspect known layer boundaries and sibling directories with unique imports. | Action tier, policy basis, evidence reasons, and recommendation are now emitted; inferred drift stays low-score/support unless stronger sibling support is available. |
125
+ | `hotspots`, `fan-in`, `fan-out`, `coupling`, `bottlenecks`, `deep-chains` | The graph facts correctly identify centrality, dependency breadth, shared symbols, hubs, or long chains, while output frames them as contextual signal or support rather than direct repair. | These are not smells by themselves; false positives are mostly product mistakes when score treats them as repair demands. | Compare with raw SCIP graph and known central modules. | Bottlenecks, coupling, and deep chains now emit action-tier metadata; deep chains de-duplicate strict suffix rows. Keep graph risk contextual except when combined with churn, cycles, or direct findings. |
126
+ | `affected`, `change-surface`, `plan-context` | The tool names real consumers, blast radius, references, calls, history, and risks for a target. | Missing index data, generated code, dynamic imports, language unsupported by current index. | Pick symbols with known callers and compare against `rg` plus compiler refs when available. | Index capability reporting, language-specific fallbacks, clearer "missing evidence" sections. |
127
+ | `self-audit` | Cheap evidence paths match the TypeScript compiler oracle on sampled symbols. | Sampling bias, non-TypeScript code, compiler config mismatch. | Repeat with scopes from different packages and compare disagreement classes. | Stratified sampling by package/file kind, persistent disagreement fixtures. |
128
+ | `health`, `health-phase`, `diff-gate` composite reports | The composite report explains its deductions and gates new direct findings without hiding signal pressure. | Treating contextual signal as direct debt, score staying perfect while signal backlog grows, baseline churn from history-derived findings. | Compare scalar changes against reviewed finding labels and suppression counts. | Action-tier identities, direct/signal score separation, suppression trust adjustments, and hidden-coupling score-count correction are recorded. |
129
+
130
+ The first TypeScript support-analysis review found accurate source-grounded output for `validateProjectConfig()` and fixed `status`/`doctor` config diagnostic parity. The Rust cross-language review confirmed that graph/source/checker-backed analyzers work on Rust, while TypeScript semantic self-audit is explicitly unavailable and frontend analyzers correctly return stack-specific empty results.
131
+
132
+ `cleanup-apply` is not an analyzer. It is an action command that should be validated through the `cleanup-plan --verify` path and normal project checks.
133
+
134
+ Navigation commands such as `stats`, `files`, `methods`, `refs`, `trace`, `deps`, `rdeps`, `system`, `surface`, `imports`, `imported-by`, `outline`, `members`, `by-kind`, `kind-counts`, `hierarchy`, `call-graph`, `code`, `dataflow`, and `slice` should be tested as evidence providers. Their success standard is referential accuracy, not whether they find a smell.
135
+
136
+ ## False-Negative Search
137
+
138
+ False negatives need active hunting because normal analyzer output cannot show what it missed.
139
+
140
+ Use these probes on each corpus:
141
+
142
+ 1. Search for large units:
143
+
144
+ ```sh
145
+ rg --files | rg '\.(ts|tsx|vue|rs)$' | xargs wc -l | sort -nr | head -30
146
+ ```
147
+
148
+ 2. Search for repeated names and local copy-paste clues:
149
+
150
+ ```sh
151
+ rg -n "TODO|copy|duplicate|refactor|extract|cleanup|unused|dead|stale"
152
+ ```
153
+
154
+ 3. Search history for repairs that should have been predicted:
155
+
156
+ ```sh
157
+ git log --oneline --grep='fix\\|bug\\|cleanup\\|refactor\\|remove\\|dead'
158
+ ```
159
+
160
+ 4. Inspect suppressions as precision labels:
161
+
162
+ ```sh
163
+ rg -n "scip-query: ignore-" src tests docs
164
+ ```
165
+
166
+ 5. For frontend repos, inspect large component split candidates by directory:
167
+
168
+ ```sh
169
+ rg --files | rg '\.(tsx|vue)$' | xargs wc -l | sort -nr | head -50
170
+ ```
171
+
172
+ The expected result of this phase is not "all analyzers are accurate." The expected result is a ranked list of detector improvements with evidence: parser gaps first, public-surface mistakes second, framework convention mistakes third, score-weight mistakes fourth.
173
+
174
+ ## Score Implications
175
+
176
+ The score model should encode reviewed action implication.
177
+
178
+ Direct findings are code or docs locations where the analyzer normally identifies a local repair. They should carry heavier deductions and should be eligible for diff-gate blocking.
179
+
180
+ Contextual signals are real patterns whose repair depends on product or architecture judgment. They should accumulate as backlog pressure, but a single signal should not be scored like dead code.
181
+
182
+ Support analyses are evidence maps. They should inform planning and other detectors, not reduce health by themselves.
183
+
184
+ Suppression counts and `self-audit` disagreement rates should modify analyzer trust. A detector with many accepted suppressions or poor compiler-oracle disagreement should still report, but its score weight should be lower until the false-positive cause is understood. Structured suppressions must keep a reason, an identity, a live expiration when temporary, and any file scope must still point at a current file.
185
+
186
+ ## Residual Future Work
187
+
188
+ No active validation ledger slice remains. Future production steps should stay small and falsifiable:
189
+
190
+ 1. Keep true co-change issue/PR labels blocked until a repository metadata provider is available; local commit-subject context is implemented.
191
+ 2. Keep locality report-only until exact consumer coverage and repair outcomes justify score integration.
192
+ 3. Keep `docs/analyzer-validation-ledger.md` current as each analyzer family receives a new implementation or corpus-confirmation result.
@@ -0,0 +1,193 @@
1
+ # Locality Analyzer Design
2
+
3
+ This document designs the missing analyzer family identified during the analyzer inventory: a tool that evaluates where extracted code belongs. It is intentionally a design document, not a production implementation.
4
+
5
+ The problem shows up most clearly after React or Vue large-component work. An agent can reduce a large file by extracting components, hooks, helpers, or composables, but it may dump all of them into a flat folder beside the original file. That can make the size metric better while making ownership, reuse, and navigation worse.
6
+
7
+ ## Core Concepts
8
+
9
+ Code locality is the placement relation between a source unit and the files that use it. It concerns real files, directories, imports, consumers, tests, and package boundaries; its essential characteristic is that code belongs at the nearest stable home that all legitimate consumers can reach without making the API broader than the concept deserves.
10
+
11
+ A source unit is a file, symbol, component, hook, composable, type, or helper that the analyzer can name and trace. It is the smallest unit whose placement can be judged from references, imports, and directory structure.
12
+
13
+ A consumer set is the set of files or symbols that import, call, render, instantiate, or otherwise rely on a source unit. Its essential role is to reveal whether a unit is private to one place, shared within a feature, shared across a domain, or actually reusable across the application.
14
+
15
+ An ownership boundary is a directory, package, route, feature, domain, or module boundary that indicates who should be allowed to change a unit. It is not just a path prefix; it is the codebase's visible grouping of reasons to change.
16
+
17
+ An abstraction level is the height of a unit's meaning relative to product code. A button primitive, route panel, invoice calculation, GraphQL client, and test fixture can all be TypeScript functions or components, but they belong at different levels because they serve different kinds of callers.
18
+
19
+ A shared folder is a directory whose name or import pattern says that multiple nearby units may depend on it. Its essential risk is that it can either preserve local reuse or become a dumping ground that erases ownership.
20
+
21
+ A global shared folder is a repository-wide shared directory such as `src/shared`, `src/lib`, `src/components`, or `packages/shared`. Its essential risk is API inflation: code placed there becomes easier to depend on from anywhere, so the placement should require cross-feature or cross-package evidence.
22
+
23
+ ## Command Shape
24
+
25
+ Proposed command:
26
+
27
+ ```sh
28
+ scip-query locality-candidates [symbol-or-file]
29
+ ```
30
+
31
+ Useful options:
32
+
33
+ ```sh
34
+ scip-query locality-candidates apps/web/src/routes/HorsesView.tsx --json
35
+ scip-query locality-candidates --scope apps/web/src --since HEAD~20
36
+ scip-query locality-candidates --changed-only --base origin/main
37
+ ```
38
+
39
+ The command should be report-only at first. Its action tier is contextual signal: it guides placement and review, but it should not move files automatically.
40
+
41
+ ## Inputs
42
+
43
+ The analyzer should combine existing evidence rather than invent a separate world model.
44
+
45
+ | Input | Source | Why it matters |
46
+ | ----------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
47
+ | Candidate source unit | Explicit argument, changed files, large component/view pressure, extract candidates | Chooses what placement is being judged |
48
+ | Consumer files and symbols | `refs`, `imported-by`, `rdeps`, call graph, JSX/Vue render facts | Shows who actually uses the unit |
49
+ | Current path and import path | filesystem path, import graph | Reveals whether the unit is already local, feature-shared, or global |
50
+ | Nearest common ancestor | consumer file paths | Finds the smallest directory all consumers share |
51
+ | Feature and route roots | path names such as `routes`, `pages`, `features`, `modules`, `domains` | Distinguishes product areas from generic infrastructure |
52
+ | Package or workspace boundary | package manifests, tsconfig references, workspace layout | Prevents app-local concepts from leaking into shared packages |
53
+ | Test adjacency | test file paths and references | Keeps test helpers near their tests unless production consumers exist |
54
+ | Naming evidence | source unit name, directory names, imported symbols | Distinguishes product concepts from generic primitives |
55
+ | Historical co-change | `co-change`, git history | Shows whether the unit changes with one feature or several |
56
+ | Existing local conventions | sibling folder names and import patterns | Avoids recommendations that fight the codebase's own organization |
57
+
58
+ ## Placement Tiers
59
+
60
+ | Tier | Recommendation | Strong evidence | Common mistake caught |
61
+ | ---------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
62
+ | `same-file` | Keep the unit in the original file. | One consumer, no independent tests, name only makes sense inside the parent. | Extracting a private branch into a needless helper file. |
63
+ | `sibling-private` | Put it next to the parent in a private local folder. | Two or more consumers under one page/component folder, no outside imports. | Creating a route-local `components` folder under global `src/components`. |
64
+ | `feature-local-shared` | Put it under the nearest feature/module shared folder. | Consumers span files in one feature root but not outside it. | Moving feature-specific hooks into app-wide `shared`. |
65
+ | `domain-shared` | Put it under a domain or bounded context folder. | Consumers cross feature roots but share domain nouns and co-change history. | Duplicating business rules in several features or over-generalizing them into `lib`. |
66
+ | `app-shared` | Put it under app-level shared UI or utility space. | Consumers cross domains inside one app and the name is generic enough for app reuse. | Keeping a genuinely reusable primitive hidden inside one feature. |
67
+ | `package-shared` | Put it in a shared workspace package. | Consumers cross package/workspace boundaries, and package API ownership is intended. | Importing across workspace internals or copying contracts between packages. |
68
+ | `no-extraction` | Do not extract, or inline it back. | One consumer, weak name, no independent concept, extraction only satisfies a size metric. | Size-score gaming through thin files and local indirection. |
69
+
70
+ The output should include confidence, reasons, counterevidence, and the exact consumer set.
71
+
72
+ ```json
73
+ {
74
+ "candidate": "apps/web/src/features/horses/HorseStatusPanel.tsx",
75
+ "currentTier": "app-shared",
76
+ "recommendedTier": "feature-local-shared",
77
+ "confidence": "medium",
78
+ "consumers": ["apps/web/src/features/horses/HorseProfile.tsx", "apps/web/src/features/horses/HorseList.tsx"],
79
+ "nearestCommonAncestor": "apps/web/src/features/horses",
80
+ "reasons": [
81
+ "all production consumers are inside one feature root",
82
+ "candidate name uses the Horses domain noun",
83
+ "no package or cross-domain consumers found"
84
+ ],
85
+ "counterevidence": ["component name is presentational enough that future app-level reuse is possible"],
86
+ "suggestedHome": "apps/web/src/features/horses/components/HorseStatusPanel.tsx"
87
+ }
88
+ ```
89
+
90
+ ## Analyzer Pairing
91
+
92
+ The locality analyzer should not replace existing analyzers. It should complete their story.
93
+
94
+ | Existing analyzer | What it says today | Locality companion question |
95
+ | ---------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
96
+ | `react-large-component-pressure` | This React component is too large. | If pieces are extracted, which ones are private, feature-local, or shared? |
97
+ | `vue-large-view-pressure` | This Vue SFC is too large. | Should extracted child components/composables live beside the view, in the feature, or in app shared? |
98
+ | `extract-candidates` | This function contains a possible extraction cluster. | Would the extracted helper have one real owner or a broader consumer set? |
99
+ | `react-hook-candidates`, `vue-composable-candidates` | Several components repeat behavior. | Is the hook/composable local to one feature or reusable across domains? |
100
+ | `recent-duplicates`, `echo` | New code duplicates older code. | Which existing owner should the new code reuse, and would reuse widen the wrong API? |
101
+ | `incomplete-migration` | A helper extraction stopped halfway. | Is the helper in the right place for all remaining call sites? |
102
+ | `co-change` | Files move together historically. | Does history imply a hidden shared owner or only a local synchronization point? |
103
+
104
+ ## Algorithm Sketch
105
+
106
+ 1. Resolve the candidate to a file or symbol.
107
+ 2. Collect direct consumers through references, imports, render facts, and reverse dependencies.
108
+ 3. Remove consumers that are tests unless the candidate is test-only.
109
+ 4. Compute the nearest common ancestor of production consumers.
110
+ 5. Identify boundary markers in and above that ancestor: `app`, `apps`, `packages`, `routes`, `pages`, `features`, `modules`, `domains`, `shared`, `components`, `hooks`, `composables`, `lib`, `utils`, `services`, `stores`, and `contracts`.
111
+ 6. Classify the current home and the smallest legitimate home.
112
+ 7. Compare names from the candidate, directories, and consumers to decide whether the concept is domain-specific or generic.
113
+ 8. Check workspace/package boundaries to prevent cross-package leakage.
114
+ 9. Use co-change history as supporting evidence, not as a hard rule.
115
+ 10. Emit a recommendation only when the consumer set and boundary evidence agree.
116
+
117
+ The first implementation can avoid automatic tree moves entirely. The valuable output is a review-grade explanation: "this extracted component is global today, but all consumers are in one feature, so feature-local shared is the smallest honest home."
118
+
119
+ ## Precision Rules
120
+
121
+ The analyzer should prefer "no confident recommendation" over pretending all placement is obvious.
122
+
123
+ Report `same-file` or `no-extraction` when a candidate has one consumer and no independent concept name.
124
+
125
+ Report `sibling-private` when all consumers sit below one component, route, or view folder and no outside production import exists.
126
+
127
+ Report `feature-local-shared` when consumers share a feature root and imports do not cross into other feature roots.
128
+
129
+ Report `domain-shared` only when path names, symbol names, or co-change evidence show the same product domain across multiple feature roots.
130
+
131
+ Report `app-shared` only when consumers cross domains inside one app and the unit is not named after one feature.
132
+
133
+ Report `package-shared` only when consumers cross package boundaries and package exports make that sharing intentional.
134
+
135
+ Downrank a recommendation when imports come only through barrels, tests are the only second consumer, the candidate name is generic but behavior is domain-specific, or the nearest common ancestor is the repo root.
136
+
137
+ ## Skill-First Option
138
+
139
+ Before production implementation, this can ship as a bundled workflow skill.
140
+
141
+ Proposed skill name:
142
+
143
+ ```text
144
+ scip-locality-review
145
+ ```
146
+
147
+ The skill would tell agents to run:
148
+
149
+ ```sh
150
+ scip-query plan-context <target> --full
151
+ scip-query imported-by <symbol>
152
+ scip-query rdeps <file>
153
+ scip-query co-change <file> --full
154
+ scip-query react-large-component-pressure <scope> --full
155
+ scip-query vue-large-view-pressure <scope> --full
156
+ ```
157
+
158
+ Then it would require the agent to answer:
159
+
160
+ 1. What is the exact consumer set?
161
+ 2. What is the nearest common owner all consumers share?
162
+ 3. Is the concept product-specific, feature-specific, app-generic, or package-level?
163
+ 4. Does the current path make the API wider than the consumer set requires?
164
+ 5. Would a move reduce imports and ownership confusion without creating a new global dumping ground?
165
+
166
+ This is a good first step because it turns the product question into a repeatable checklist while we gather validation labels for the eventual command.
167
+
168
+ ## Validation Plan
169
+
170
+ Use the validation corpus from `docs/analyzer-validation-protocol.md` and track the work under `docs/analyzer-validation-ledger.md`.
171
+
172
+ For React, inspect Vega_2.0 large components and hook candidates. A true positive is a recommendation that would place an extracted unit closer to its actual consumers without hiding a real shared primitive.
173
+
174
+ For Vue, inspect Stable_Management large views and composable candidates. A true positive is a recommendation that distinguishes route-local child components from feature-level composables and app-level UI primitives.
175
+
176
+ For scip-query itself, inspect analyzer/helper extractions. A true positive is a recommendation that keeps detector-private helpers near their detector unless multiple detector families actually consume them.
177
+
178
+ For Rust smoke coverage, run the command only after SCIP data supports the same source-unit questions. Until then, locality validation on Rust should be marked unsupported rather than failed.
179
+
180
+ Validation result: `docs/validation/2026-06-21-locality-analyzer-validation-result.md` recommends a report-only or skill-first implementation, with `actionTier: "signal"` and explicit consumer-coverage caveats. React `.tsx` samples had usable `rdeps` evidence, but Vue SFC samples had weak reverse-dependency coverage, so the first implementation must not recommend concrete destinations unless exact consumers are known.
181
+
182
+ ## Score Integration
183
+
184
+ Locality findings should not immediately reduce health like dead code. They are contextual signals.
185
+
186
+ The health score can later use them as signal backlog pressure when they combine with other evidence:
187
+
188
+ - Large component pressure plus globalized local children.
189
+ - Extract candidates plus one-consumer helper files.
190
+ - Recent duplicates plus a clear existing local owner.
191
+ - Co-change clusters plus no shared owner directory.
192
+
193
+ The score should not punish a single "could be more local" suggestion. It should punish repeated evidence that code organization is being flattened until ownership is unclear.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scip-query",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Evidence and verification for AI coding agents: map code, reuse concepts, finish migrations, and gate diffs.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -149,6 +149,10 @@
149
149
  "import": "./dist/queries/isolated.js",
150
150
  "types": "./dist/queries/isolated.d.ts"
151
151
  },
152
+ "./queries/locality-candidates": {
153
+ "import": "./dist/queries/locality-candidates.js",
154
+ "types": "./dist/queries/locality-candidates.d.ts"
155
+ },
152
156
  "./queries/members": {
153
157
  "import": "./dist/queries/members.js",
154
158
  "types": "./dist/queries/members.d.ts"
@@ -257,6 +261,10 @@
257
261
  "import": "./dist/queries/unused-params.js",
258
262
  "types": "./dist/queries/unused-params.d.ts"
259
263
  },
264
+ "./queries/unused-imports": {
265
+ "import": "./dist/queries/unused-imports.js",
266
+ "types": "./dist/queries/unused-imports.d.ts"
267
+ },
260
268
  "./queries/wrapper-candidates": {
261
269
  "import": "./dist/queries/wrapper-candidates.js",
262
270
  "types": "./dist/queries/wrapper-candidates.d.ts"
@@ -273,12 +281,14 @@
273
281
  "scripts": {
274
282
  "build": "node --max-old-space-size=8192 ./node_modules/tsup/dist/cli-default.js",
275
283
  "dev": "tsup --watch",
284
+ "format": "prettier --write \"{src,tests,scripts}/**/*.{ts,tsx,js,mjs,json}\" \"*.{ts,js,json}\"",
285
+ "format:check": "prettier --check \"{src,tests,scripts}/**/*.{ts,tsx,js,mjs,json}\" \"*.{ts,js,json}\"",
276
286
  "test": "vitest run",
277
287
  "test:watch": "vitest",
278
288
  "typecheck": "tsc --noEmit",
279
- "lint": "eslint src tests tsup.config.ts",
289
+ "lint": "npm run format:check && eslint src tests tsup.config.ts",
280
290
  "calibrate": "node scripts/accuracy-calibration.mjs",
281
- "docs:commands": "vite-node scripts/render-command-reference.ts",
291
+ "docs:commands": "vite-node scripts/render-command-reference.ts --write",
282
292
  "prepublishOnly": "npm run build",
283
293
  "postinstall": "node dist/postinstall.js || true"
284
294
  },
@@ -337,6 +347,7 @@
337
347
  "@types/node": "^22.10.0",
338
348
  "eslint": "^10.2.0",
339
349
  "globals": "^17.5.0",
350
+ "prettier": "^3.8.4",
340
351
  "tsup": "^8.3.0",
341
352
  "typescript": "^5.7.0",
342
353
  "typescript-eslint": "^8.58.1",