scip-query 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -43
- package/dist/chunk-26DOJ63W.js +161 -0
- package/dist/chunk-2UELLEBI.js +1 -0
- package/dist/{chunk-4PDAL6IL.js → chunk-4JCSOF2O.js} +3 -3
- package/dist/{chunk-6SXADWLW.js → chunk-5OMVSV6E.js} +13 -5
- package/dist/{chunk-KPPHZCZJ.js → chunk-7HK5ZLOE.js} +28 -46
- package/dist/{chunk-7RLE5EWE.js → chunk-7KIMF5PV.js} +34 -13
- package/dist/chunk-AXQKUYKF.js +1442 -0
- package/dist/chunk-C7H5WBTJ.js +46 -0
- package/dist/{chunk-NHBZIL2J.js → chunk-CHDJXYBG.js} +3 -28
- package/dist/{chunk-KCBMVQL5.js → chunk-CPVAQJEC.js} +13 -5
- package/dist/{chunk-ZQIIPFD7.js → chunk-DH7G3DDV.js} +2 -2
- package/dist/{chunk-BOVXCR46.js → chunk-EOROMIFO.js} +14 -6
- package/dist/{chunk-2CKGIR6G.js → chunk-EPWLXXBL.js} +3 -3
- package/dist/{chunk-5RMYT5WH.js → chunk-F7XU27LU.js} +2 -2
- package/dist/{chunk-63G7IQTD.js → chunk-FYYOWQXK.js} +20 -40
- package/dist/chunk-GEXE2T6I.js +87 -0
- package/dist/{chunk-DGUPQSOR.js → chunk-GJDHTTR2.js} +11 -4
- package/dist/chunk-GSH2FPKV.js +87 -0
- package/dist/{chunk-NUZ4OMU3.js → chunk-GU2H5QRN.js} +2 -2
- package/dist/{chunk-Z6YZJ36C.js → chunk-HJZUSUPU.js} +8 -4
- package/dist/{chunk-LAWMH22O.js → chunk-HLKAFWWJ.js} +82 -3
- package/dist/{chunk-HPFZLISB.js → chunk-HLUS2HEB.js} +2 -2
- package/dist/{chunk-H2MDONBU.js → chunk-J3JSOSUO.js} +9 -6
- package/dist/{chunk-7PBOG4YE.js → chunk-KBOQX573.js} +2 -2
- package/dist/{chunk-HDSRORNV.js → chunk-KKCHYLVI.js} +17 -11
- package/dist/{chunk-HMLMH7VZ.js → chunk-LFJQVJYJ.js} +2 -2
- package/dist/{chunk-4EXL2CUA.js → chunk-LQJUPXQY.js} +16 -8
- package/dist/{chunk-ITZ3DDOG.js → chunk-MPGIHELS.js} +18 -3
- package/dist/chunk-NFS5W3PP.js +37 -0
- package/dist/chunk-NG5F43OU.js +200 -0
- package/dist/{chunk-DCKMSTJ4.js → chunk-O7Q7FDUJ.js} +22 -14
- package/dist/{chunk-UJQN5N3I.js → chunk-OIDHN6GD.js} +6 -3
- package/dist/{chunk-Z4GHE2HD.js → chunk-P3E6L7KW.js} +6 -2
- package/dist/{chunk-BNN2RKD2.js → chunk-P4WO3BBW.js} +3 -3
- package/dist/{chunk-QOV2R2WT.js → chunk-QIXNAB5K.js} +42 -2
- package/dist/{chunk-NWCE4CIC.js → chunk-SMDCNPMK.js} +11 -28
- package/dist/{chunk-SEFSL2GF.js → chunk-TOIEB3LG.js} +2 -2
- package/dist/{chunk-4XHWPRAX.js → chunk-UGQKAVCD.js} +3 -3
- package/dist/{chunk-OVPLOMPY.js → chunk-UQEQ6AHX.js} +7 -4
- package/dist/{chunk-ZK6GXM3J.js → chunk-VIYSWZCO.js} +3 -3
- package/dist/chunk-VJJKSGIX.js +121 -0
- package/dist/{chunk-N5KEREIA.js → chunk-VT4JBH6L.js} +19 -7
- package/dist/{chunk-7LLPRPR5.js → chunk-WGAD3GNR.js} +2 -2
- package/dist/chunk-YDBXNPYU.js +69 -0
- package/dist/chunk-YY4QGUQ5.js +84 -0
- package/dist/{chunk-FGXRVW7G.js → chunk-YZ6L7GFO.js} +2 -2
- package/dist/{chunk-W4ALF422.js → chunk-ZEUCXQBN.js} +3 -3
- package/dist/cli.js +2697 -1054
- package/dist/{db-BNVVZSfP.d.ts → db-ShvwGDKf.d.ts} +12 -19
- package/dist/index.d.ts +15 -15
- package/dist/index.js +263 -234
- package/dist/postinstall.js +5 -76
- package/dist/queries/affected.d.ts +1 -1
- package/dist/queries/affected.js +3 -3
- package/dist/queries/bottlenecks.d.ts +1 -1
- package/dist/queries/bottlenecks.js +2 -2
- package/dist/queries/by-kind.d.ts +1 -1
- package/dist/queries/by-kind.js +2 -2
- package/dist/queries/call-graph.d.ts +1 -1
- package/dist/queries/call-graph.js +3 -3
- package/dist/queries/change-surface.d.ts +2 -2
- package/dist/queries/change-surface.js +3 -3
- package/dist/queries/code.d.ts +1 -1
- package/dist/queries/code.js +3 -3
- package/dist/queries/complexity-hotspots.d.ts +1 -1
- package/dist/queries/complexity-hotspots.js +3 -3
- package/dist/queries/complexity.d.ts +1 -1
- package/dist/queries/complexity.js +3 -3
- package/dist/queries/convergence.d.ts +1 -1
- package/dist/queries/convergence.js +3 -3
- package/dist/queries/coupling.d.ts +1 -1
- package/dist/queries/coupling.js +3 -1
- package/dist/queries/cycles.d.ts +1 -1
- package/dist/queries/cycles.js +3 -2
- package/dist/queries/dataflow.d.ts +1 -1
- package/dist/queries/dataflow.js +3 -3
- package/dist/queries/dead.d.ts +1 -1
- package/dist/queries/dead.js +4 -3
- package/dist/queries/deep-chains.d.ts +1 -1
- package/dist/queries/deep-chains.js +3 -2
- package/dist/queries/deps.d.ts +1 -1
- package/dist/queries/deps.js +3 -1
- package/dist/queries/diff-impact.d.ts +2 -2
- package/dist/queries/diff-impact.js +2 -3
- package/dist/queries/doc-coverage.d.ts +1 -1
- package/dist/queries/doc-coverage.js +2 -2
- package/dist/queries/drift.d.ts +1 -1
- package/dist/queries/drift.js +3 -2
- package/dist/queries/extract-candidates.d.ts +1 -1
- package/dist/queries/extract-candidates.js +3 -3
- package/dist/queries/fan.d.ts +1 -1
- package/dist/queries/fan.js +3 -2
- package/dist/queries/files.d.ts +1 -1
- package/dist/queries/health.d.ts +1 -1
- package/dist/queries/health.js +14 -14
- package/dist/queries/hierarchy.d.ts +1 -1
- package/dist/queries/hierarchy.js +3 -2
- package/dist/queries/hotspots.d.ts +1 -1
- package/dist/queries/hotspots.js +2 -2
- package/dist/queries/imports.d.ts +1 -1
- package/dist/queries/imports.js +3 -2
- package/dist/queries/index.d.ts +1 -2
- package/dist/queries/index.js +46 -51
- package/dist/queries/isolated.d.ts +1 -1
- package/dist/queries/isolated.js +4 -3
- package/dist/queries/members.d.ts +2 -2
- package/dist/queries/members.js +3 -2
- package/dist/queries/methods.d.ts +1 -1
- package/dist/queries/methods.js +2 -2
- package/dist/queries/outline.d.ts +1 -1
- package/dist/queries/outline.js +3 -2
- package/dist/queries/passthrough-candidates.d.ts +1 -1
- package/dist/queries/passthrough-candidates.js +3 -3
- package/dist/queries/redundant-reexports.d.ts +1 -1
- package/dist/queries/redundant-reexports.js +4 -2
- package/dist/queries/refs.d.ts +1 -1
- package/dist/queries/refs.js +3 -1
- package/dist/queries/similar-chains.d.ts +1 -1
- package/dist/queries/similar-chains.js +3 -2
- package/dist/queries/similar-files.d.ts +1 -1
- package/dist/queries/similar-files.js +3 -2
- package/dist/queries/similar-signatures.d.ts +1 -1
- package/dist/queries/similar-signatures.js +2 -2
- package/dist/queries/similar.d.ts +1 -1
- package/dist/queries/similar.js +3 -3
- package/dist/queries/slice.d.ts +2 -2
- package/dist/queries/slice.js +3 -3
- package/dist/queries/stale-abstractions.d.ts +1 -1
- package/dist/queries/stale-abstractions.js +3 -3
- package/dist/queries/stats.d.ts +1 -1
- package/dist/queries/surface.d.ts +1 -1
- package/dist/queries/surface.js +3 -2
- package/dist/queries/symbols.d.ts +1 -1
- package/dist/queries/symbols.js +3 -2
- package/dist/queries/system.d.ts +1 -1
- package/dist/queries/system.js +3 -2
- package/dist/queries/trace.d.ts +1 -1
- package/dist/queries/trace.js +3 -1
- package/dist/queries/wrapper-candidates.d.ts +1 -1
- package/dist/queries/wrapper-candidates.js +3 -3
- package/dist/reindex-worker.js +24 -12
- package/package.json +6 -1
- package/IMPROVEMENTS.md +0 -143
- package/PLAN.md +0 -320
- package/dist/chunk-2CKGIR6G.js.map +0 -1
- package/dist/chunk-3UOUTZQT.js +0 -45
- package/dist/chunk-3UOUTZQT.js.map +0 -1
- package/dist/chunk-4EXL2CUA.js.map +0 -1
- package/dist/chunk-4PDAL6IL.js.map +0 -1
- package/dist/chunk-4TYLS5XX.js.map +0 -1
- package/dist/chunk-4XHWPRAX.js.map +0 -1
- package/dist/chunk-5RMYT5WH.js.map +0 -1
- package/dist/chunk-63G7IQTD.js.map +0 -1
- package/dist/chunk-6SXADWLW.js.map +0 -1
- package/dist/chunk-74RFWB5T.js.map +0 -1
- package/dist/chunk-7LLPRPR5.js.map +0 -1
- package/dist/chunk-7PBOG4YE.js.map +0 -1
- package/dist/chunk-7RLE5EWE.js.map +0 -1
- package/dist/chunk-7UCKSQRS.js +0 -55
- package/dist/chunk-7UCKSQRS.js.map +0 -1
- package/dist/chunk-BNN2RKD2.js.map +0 -1
- package/dist/chunk-BOVXCR46.js.map +0 -1
- package/dist/chunk-D567NFIF.js +0 -65
- package/dist/chunk-D567NFIF.js.map +0 -1
- package/dist/chunk-DCKMSTJ4.js.map +0 -1
- package/dist/chunk-DEZKCZXD.js +0 -40
- package/dist/chunk-DEZKCZXD.js.map +0 -1
- package/dist/chunk-DGUPQSOR.js.map +0 -1
- package/dist/chunk-DVWGWHFW.js +0 -99
- package/dist/chunk-DVWGWHFW.js.map +0 -1
- package/dist/chunk-EQYLEQCW.js +0 -46
- package/dist/chunk-EQYLEQCW.js.map +0 -1
- package/dist/chunk-FGXRVW7G.js.map +0 -1
- package/dist/chunk-H2MDONBU.js.map +0 -1
- package/dist/chunk-HB7MRLLL.js +0 -76
- package/dist/chunk-HB7MRLLL.js.map +0 -1
- package/dist/chunk-HDSRORNV.js.map +0 -1
- package/dist/chunk-HMLMH7VZ.js.map +0 -1
- package/dist/chunk-HPFZLISB.js.map +0 -1
- package/dist/chunk-HZBC7PPD.js +0 -88
- package/dist/chunk-HZBC7PPD.js.map +0 -1
- package/dist/chunk-ITZ3DDOG.js.map +0 -1
- package/dist/chunk-JJP7KQND.js +0 -1
- package/dist/chunk-JJP7KQND.js.map +0 -1
- package/dist/chunk-KCBMVQL5.js.map +0 -1
- package/dist/chunk-KPPHZCZJ.js.map +0 -1
- package/dist/chunk-LAWMH22O.js.map +0 -1
- package/dist/chunk-MCUX5LA7.js +0 -103
- package/dist/chunk-MCUX5LA7.js.map +0 -1
- package/dist/chunk-MGNMHKX3.js.map +0 -1
- package/dist/chunk-N5KEREIA.js.map +0 -1
- package/dist/chunk-NHBZIL2J.js.map +0 -1
- package/dist/chunk-NUZ4OMU3.js.map +0 -1
- package/dist/chunk-NWCE4CIC.js.map +0 -1
- package/dist/chunk-OVPLOMPY.js.map +0 -1
- package/dist/chunk-QOV2R2WT.js.map +0 -1
- package/dist/chunk-SEFSL2GF.js.map +0 -1
- package/dist/chunk-UJQN5N3I.js.map +0 -1
- package/dist/chunk-W4ALF422.js.map +0 -1
- package/dist/chunk-Z4GHE2HD.js.map +0 -1
- package/dist/chunk-Z6YZJ36C.js.map +0 -1
- package/dist/chunk-ZK6GXM3J.js.map +0 -1
- package/dist/chunk-ZOGY2V3N.js +0 -158
- package/dist/chunk-ZOGY2V3N.js.map +0 -1
- package/dist/chunk-ZQIIPFD7.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/postinstall.js.map +0 -1
- package/dist/queries/affected.js.map +0 -1
- package/dist/queries/bottlenecks.js.map +0 -1
- package/dist/queries/by-kind.js.map +0 -1
- package/dist/queries/call-graph.js.map +0 -1
- package/dist/queries/change-surface.js.map +0 -1
- package/dist/queries/clean-signature.js.map +0 -1
- package/dist/queries/code.js.map +0 -1
- package/dist/queries/complexity-hotspots.js.map +0 -1
- package/dist/queries/complexity.js.map +0 -1
- package/dist/queries/convergence.js.map +0 -1
- package/dist/queries/coupling.js.map +0 -1
- package/dist/queries/cycles.js.map +0 -1
- package/dist/queries/dataflow.js.map +0 -1
- package/dist/queries/dead.js.map +0 -1
- package/dist/queries/deep-chains.js.map +0 -1
- package/dist/queries/deps.js.map +0 -1
- package/dist/queries/diff-impact.js.map +0 -1
- package/dist/queries/doc-coverage.js.map +0 -1
- package/dist/queries/drift.js.map +0 -1
- package/dist/queries/extract-candidates.js.map +0 -1
- package/dist/queries/fan.js.map +0 -1
- package/dist/queries/files.js.map +0 -1
- package/dist/queries/health.js.map +0 -1
- package/dist/queries/hierarchy.js.map +0 -1
- package/dist/queries/hotspots.js.map +0 -1
- package/dist/queries/imports.js.map +0 -1
- package/dist/queries/index.js.map +0 -1
- package/dist/queries/isolated.js.map +0 -1
- package/dist/queries/members.js.map +0 -1
- package/dist/queries/methods.js.map +0 -1
- package/dist/queries/outline.js.map +0 -1
- package/dist/queries/passthrough-candidates.js.map +0 -1
- package/dist/queries/redundant-reexports.js.map +0 -1
- package/dist/queries/refs.js.map +0 -1
- package/dist/queries/similar-chains.js.map +0 -1
- package/dist/queries/similar-files.js.map +0 -1
- package/dist/queries/similar-signatures.js.map +0 -1
- package/dist/queries/similar.js.map +0 -1
- package/dist/queries/slice.js.map +0 -1
- package/dist/queries/stale-abstractions.js.map +0 -1
- package/dist/queries/stats.js.map +0 -1
- package/dist/queries/surface.js.map +0 -1
- package/dist/queries/symbols.js.map +0 -1
- package/dist/queries/system.js.map +0 -1
- package/dist/queries/test-coverage.d.ts +0 -22
- package/dist/queries/test-coverage.js +0 -11
- package/dist/queries/test-coverage.js.map +0 -1
- package/dist/queries/trace.js.map +0 -1
- package/dist/queries/wrapper-candidates.js.map +0 -1
- package/dist/reindex-worker.js.map +0 -1
- package/docs/AGENT_GUIDE.md +0 -359
- package/reports/debloat/2026-04-10-scip-query-self-audit.md +0 -161
- package/src/cli.ts +0 -1480
- package/src/config.ts +0 -117
- package/src/db.ts +0 -127
- package/src/gitignore-filter.ts +0 -143
- package/src/index.ts +0 -11
- package/src/postinstall.ts +0 -8
- package/src/queries/affected.ts +0 -86
- package/src/queries/bottlenecks.ts +0 -67
- package/src/queries/by-kind.ts +0 -204
- package/src/queries/call-graph.ts +0 -66
- package/src/queries/change-surface.ts +0 -110
- package/src/queries/clean-signature.ts +0 -22
- package/src/queries/code.ts +0 -101
- package/src/queries/complexity-hotspots.ts +0 -119
- package/src/queries/complexity.ts +0 -152
- package/src/queries/convergence.ts +0 -82
- package/src/queries/coupling.ts +0 -99
- package/src/queries/cycles.ts +0 -78
- package/src/queries/dataflow.ts +0 -128
- package/src/queries/dead.ts +0 -122
- package/src/queries/deep-chains.ts +0 -59
- package/src/queries/deps.ts +0 -46
- package/src/queries/diff-impact.ts +0 -204
- package/src/queries/doc-coverage.ts +0 -86
- package/src/queries/drift.ts +0 -224
- package/src/queries/extract-candidates.ts +0 -167
- package/src/queries/fan.ts +0 -148
- package/src/queries/files.ts +0 -16
- package/src/queries/health.ts +0 -324
- package/src/queries/hierarchy.ts +0 -49
- package/src/queries/hotspots.ts +0 -53
- package/src/queries/imports.ts +0 -95
- package/src/queries/index.ts +0 -45
- package/src/queries/isolated.ts +0 -67
- package/src/queries/members.ts +0 -54
- package/src/queries/methods.ts +0 -27
- package/src/queries/outline.ts +0 -52
- package/src/queries/passthrough-candidates.ts +0 -94
- package/src/queries/redundant-reexports.ts +0 -170
- package/src/queries/refs.ts +0 -27
- package/src/queries/similar-chains.ts +0 -314
- package/src/queries/similar-files.ts +0 -140
- package/src/queries/similar-signatures.ts +0 -151
- package/src/queries/similar.ts +0 -305
- package/src/queries/slice.ts +0 -154
- package/src/queries/stale-abstractions.ts +0 -82
- package/src/queries/stats.ts +0 -22
- package/src/queries/surface.ts +0 -34
- package/src/queries/symbols.ts +0 -39
- package/src/queries/system.ts +0 -86
- package/src/queries/test-coverage.ts +0 -106
- package/src/queries/trace.ts +0 -55
- package/src/queries/wrapper-candidates.ts +0 -112
- package/src/query-support.ts +0 -226
- package/src/reindex/detect.ts +0 -58
- package/src/reindex/index.ts +0 -153
- package/src/reindex/indexers.ts +0 -220
- package/src/reindex/install.ts +0 -125
- package/src/reindex-worker.ts +0 -35
- package/src/setup.ts +0 -202
- package/src/symbol-parser.ts +0 -278
- package/src/types.ts +0 -654
- package/src/watch.ts +0 -274
- package/tests/gitignore-filter.test.ts +0 -48
- package/tests/queries.test.ts +0 -300
- package/tests/symbol-parser.test.ts +0 -157
- package/tsconfig.json +0 -20
- package/tsup.config.ts +0 -40
- package/vitest.config.ts +0 -7
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ For goal-oriented usage guides (not just command reference), see **[Agent Guide]
|
|
|
12
12
|
- **[Write an implementation plan](docs/AGENT_GUIDE.md#workflow-2-write-a-concrete-implementation-plan)** — identify contracts, map dependencies, find reusable code
|
|
13
13
|
- **[De-bloat a codebase](docs/AGENT_GUIDE.md#workflow-3-clean-up-and-de-bloat-a-codebase)** — prioritized cleanup from dead code to pattern drift
|
|
14
14
|
- **[Assess code quality](docs/AGENT_GUIDE.md#workflow-4-assess-code-quality-and-risk)** — health score, complexity hotspots, coupling risks
|
|
15
|
-
- **[Verify change impact](docs/AGENT_GUIDE.md#workflow-5-understand-impact-after-making-changes)** — diff impact, transitive blast radius,
|
|
15
|
+
- **[Verify change impact](docs/AGENT_GUIDE.md#workflow-5-understand-impact-after-making-changes)** — diff impact, transitive blast radius, consumer blast radius
|
|
16
16
|
|
|
17
17
|
## Quick Start
|
|
18
18
|
|
|
@@ -53,6 +53,8 @@ scip-query diff-impact # what did my changes affect?
|
|
|
53
53
|
| Dart | scip-dart | [releases](https://github.com/nicovince/scip-dart/releases) |
|
|
54
54
|
| PHP | scip-php | [releases](https://github.com/nicovince/scip-php/releases) |
|
|
55
55
|
|
|
56
|
+
For Python, the npm package is `scip-python-plus`. Depending on which version you installed, the executable on your `PATH` may be `scip-python`, `scip-python-plus`, or both. `scip-query` now accepts either name.
|
|
57
|
+
|
|
56
58
|
## How It Works
|
|
57
59
|
|
|
58
60
|
1. A SCIP indexer analyzes your source code using the actual compiler/type checker and produces a `index.scip` protobuf file containing every symbol, definition, and reference — fully type-resolved.
|
|
@@ -461,10 +463,10 @@ scip-query dead src/utils --skip-barrels --include-members
|
|
|
461
463
|
**Options:**
|
|
462
464
|
- `--min-loc <n>` — Only show symbols >= N lines (default: 1)
|
|
463
465
|
- `--include-tests` — Include test files in results (excluded by default)
|
|
464
|
-
- `--skip-barrels` — Ignore references from barrel re-export files
|
|
466
|
+
- `--skip-barrels` — Ignore references from inactive barrel re-export files
|
|
465
467
|
- `--include-members` — Include class members (module-level only by default)
|
|
466
468
|
|
|
467
|
-
**Value:** Find code you can delete. The `--skip-barrels` flag is key
|
|
469
|
+
**Value:** Find code you can delete. The `--skip-barrels` flag is key when a codebase has unused barrels, but it now keeps live entry-surface barrels counted so active exports do not look dead.
|
|
468
470
|
|
|
469
471
|
---
|
|
470
472
|
|
|
@@ -510,31 +512,6 @@ scip-query doc-coverage --min-loc 5
|
|
|
510
512
|
|
|
511
513
|
---
|
|
512
514
|
|
|
513
|
-
#### `test-coverage [symbol]`
|
|
514
|
-
|
|
515
|
-
Check if symbols are referenced by test files. Without a symbol argument, shows a summary percentage. With a symbol, shows which specific test files cover it.
|
|
516
|
-
|
|
517
|
-
```bash
|
|
518
|
-
scip-query test-coverage
|
|
519
|
-
# Test coverage: 45%
|
|
520
|
-
# Total symbols: 95
|
|
521
|
-
# Covered: 43
|
|
522
|
-
# Not covered: 52
|
|
523
|
-
|
|
524
|
-
scip-query test-coverage AuthService
|
|
525
|
-
# [covered] AuthService (src/services/auth.service.ts)
|
|
526
|
-
# ← src/__tests__/auth.test.ts
|
|
527
|
-
# [NOT COVERED] AuthService:logout() (src/services/auth.service.ts)
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
**Options:**
|
|
531
|
-
- `-s, --scope <path>` — Limit to files matching path
|
|
532
|
-
- `--min-loc <n>` — Minimum LOC for summary mode (default: 3)
|
|
533
|
-
|
|
534
|
-
**Value:** Reference-based test coverage — which symbols does your test suite actually exercise? Not execution coverage, but structural coverage: "do tests at least reference this code?"
|
|
535
|
-
|
|
536
|
-
---
|
|
537
|
-
|
|
538
515
|
### Codebase Metrics
|
|
539
516
|
|
|
540
517
|
These commands measure structural properties of the codebase — hotspots, coupling, bottlenecks, fan-in/out.
|
|
@@ -556,7 +533,7 @@ scip-query hotspots -n 15
|
|
|
556
533
|
- `-n, --limit <n>` — Number of results (default: 30)
|
|
557
534
|
- `-s, --scope <path>` — Limit to files matching path
|
|
558
535
|
|
|
559
|
-
**Value:** Identify the symbols where a bug or breaking change would affect the most consumers. Hotspots deserve the most careful review
|
|
536
|
+
**Value:** Identify the symbols where a bug or breaking change would affect the most consumers. Hotspots deserve the most careful review and the most stable interfaces.
|
|
560
537
|
|
|
561
538
|
---
|
|
562
539
|
|
|
@@ -581,7 +558,7 @@ scip-query fan-in -n 10
|
|
|
581
558
|
- `-n, --limit <n>` — Number of results for top mode (default: 30)
|
|
582
559
|
- `-s, --scope <path>` — Limit to files matching path
|
|
583
560
|
|
|
584
|
-
**Value:** High fan-in = widely depended upon. Changes to high fan-in symbols have large blast radius. These symbols should have stable interfaces and
|
|
561
|
+
**Value:** High fan-in = widely depended upon. Changes to high fan-in symbols have large blast radius. These symbols should have stable interfaces and careful review.
|
|
585
562
|
|
|
586
563
|
---
|
|
587
564
|
|
|
@@ -871,19 +848,19 @@ scip-query affected login --max-depth 3
|
|
|
871
848
|
|
|
872
849
|
#### `change-surface <file>`
|
|
873
850
|
|
|
874
|
-
Pre-change briefing for a file: every exported symbol, consumer count,
|
|
851
|
+
Pre-change briefing for a file: every exported symbol, consumer count, and blast-radius risk.
|
|
875
852
|
|
|
876
853
|
```bash
|
|
877
854
|
scip-query change-surface auth.service.ts
|
|
878
855
|
# File: src/services/auth.service.ts
|
|
879
|
-
#
|
|
856
|
+
# External consumers: 45
|
|
880
857
|
#
|
|
881
|
-
# 1-50 AuthService [12 consumers]
|
|
882
|
-
# 5-20 login() [8 consumers]
|
|
883
|
-
# 22-35 logout() [
|
|
858
|
+
# 1-50 AuthService [12 consumers] *** HIGH RISK ***
|
|
859
|
+
# 5-20 login() [8 consumers] * medium risk *
|
|
860
|
+
# 22-35 logout() [0 consumers]
|
|
884
861
|
```
|
|
885
862
|
|
|
886
|
-
**Value:** One command before modifying any file. Shows what's exported, who uses it,
|
|
863
|
+
**Value:** One command before modifying any file. Shows what's exported, who uses it, and which symbols carry the largest downstream blast radius.
|
|
887
864
|
|
|
888
865
|
---
|
|
889
866
|
|
|
@@ -897,13 +874,12 @@ scip-query diff-impact --base main
|
|
|
897
874
|
# Changed files: 3
|
|
898
875
|
# Changed symbols: 12
|
|
899
876
|
# Affected consumer files: 28
|
|
900
|
-
# Test coverage: 67%
|
|
901
877
|
```
|
|
902
878
|
|
|
903
879
|
**Options:**
|
|
904
880
|
- `--base <ref>` — Git ref to diff against (default: HEAD)
|
|
905
881
|
|
|
906
|
-
**Value:** Run before committing. Shows everything your changes affect
|
|
882
|
+
**Value:** Run before committing. Shows everything your changes affect and which consumer files sit downstream of the changed symbols.
|
|
907
883
|
|
|
908
884
|
---
|
|
909
885
|
|
|
@@ -914,15 +890,12 @@ scip-query diff-impact --base main
|
|
|
914
890
|
Detect files that deviate from their directory's typical dependency pattern.
|
|
915
891
|
|
|
916
892
|
```bash
|
|
917
|
-
scip-query drift
|
|
893
|
+
scip-query drift
|
|
918
894
|
# src/services/legacy-auth.ts (65% deviation from src/services)
|
|
919
895
|
# Missing expected: validator.ts, logger.ts
|
|
920
896
|
# Unexpected: raw-sql.ts, deprecated-crypto.ts
|
|
921
897
|
```
|
|
922
898
|
|
|
923
|
-
**Options:**
|
|
924
|
-
- `--min-deviation <n>` — Minimum deviation % to report (default: 30)
|
|
925
|
-
|
|
926
899
|
**Value:** Finds files that don't follow their neighbors' conventions. The outliers are either legacy code needing migration or intentional exceptions needing documentation.
|
|
927
900
|
|
|
928
901
|
---
|
|
@@ -1149,7 +1122,7 @@ scip-query redundant-reexports
|
|
|
1149
1122
|
- `-s, --scope <path>` — Limit to files matching path
|
|
1150
1123
|
- `-n, --limit <n>` — Number of results (default: 30)
|
|
1151
1124
|
|
|
1152
|
-
**Value:** Finds dead entries in barrel files.
|
|
1125
|
+
**Value:** Finds dead entries in inactive barrel files. Live barrels are skipped so shared entry surfaces like package roots and CLI registries do not show up as false positives.
|
|
1153
1126
|
|
|
1154
1127
|
---
|
|
1155
1128
|
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findFirstSymbolMatch,
|
|
3
|
+
getSourceImports,
|
|
4
|
+
resolveIndexedFile
|
|
5
|
+
} from "./chunk-AXQKUYKF.js";
|
|
6
|
+
import {
|
|
7
|
+
isModuleLikeSymbol,
|
|
8
|
+
leafName,
|
|
9
|
+
shortenSymbol
|
|
10
|
+
} from "./chunk-QIXNAB5K.js";
|
|
11
|
+
|
|
12
|
+
// src/queries/imports.ts
|
|
13
|
+
function imports(db, filePattern) {
|
|
14
|
+
const importer = resolveIndexedFile(db, filePattern);
|
|
15
|
+
if (!importer) return [];
|
|
16
|
+
const rows = db.all(
|
|
17
|
+
`SELECT DISTINCT gs.symbol, def_d.relative_path AS from_file, imp_d.relative_path AS importer
|
|
18
|
+
FROM mentions m
|
|
19
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
20
|
+
JOIN documents imp_d ON c.document_id = imp_d.id
|
|
21
|
+
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
22
|
+
LEFT JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
|
|
23
|
+
LEFT JOIN documents def_d ON der.document_id = def_d.id
|
|
24
|
+
WHERE imp_d.relative_path = ?
|
|
25
|
+
AND m.role = 2
|
|
26
|
+
ORDER BY def_d.relative_path, gs.symbol`,
|
|
27
|
+
importer
|
|
28
|
+
);
|
|
29
|
+
const indexedResults = rows.filter((row) => !db.isIgnored(row.importer)).map((r) => ({
|
|
30
|
+
symbol: r.symbol,
|
|
31
|
+
shortName: shortenSymbol(r.symbol),
|
|
32
|
+
fromFile: r.from_file ?? "(external)"
|
|
33
|
+
}));
|
|
34
|
+
if (indexedResults.length > 0) {
|
|
35
|
+
return indexedResults;
|
|
36
|
+
}
|
|
37
|
+
return getSourceImports(db, importer).map((entry) => ({
|
|
38
|
+
symbol: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
|
|
39
|
+
shortName: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
|
|
40
|
+
fromFile: entry.sourcePath ?? "(external)"
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
function importedBy(db, symbolPattern) {
|
|
44
|
+
const rows = db.all(
|
|
45
|
+
`SELECT DISTINCT gs.symbol, d.relative_path AS importer
|
|
46
|
+
FROM mentions m
|
|
47
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
48
|
+
JOIN documents d ON c.document_id = d.id
|
|
49
|
+
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
50
|
+
WHERE gs.symbol LIKE ?
|
|
51
|
+
AND m.role = 2
|
|
52
|
+
ORDER BY d.relative_path`,
|
|
53
|
+
`%${symbolPattern}%`
|
|
54
|
+
);
|
|
55
|
+
const indexedResults = rows.filter((r) => !db.isIgnored(r.importer)).map((r) => ({
|
|
56
|
+
symbol: r.symbol,
|
|
57
|
+
shortName: shortenSymbol(r.symbol),
|
|
58
|
+
fromFile: r.importer
|
|
59
|
+
}));
|
|
60
|
+
if (indexedResults.length > 0) {
|
|
61
|
+
return indexedResults;
|
|
62
|
+
}
|
|
63
|
+
const target = findFirstSymbolMatch(db, symbolPattern);
|
|
64
|
+
const targetFile = target?.relativePath ?? null;
|
|
65
|
+
const targetLeaf = target ? leafName(target.symbol) : symbolPattern.replace(/\(\)$/, "");
|
|
66
|
+
const targetIsModule = target ? isModuleLikeSymbol(target.symbol) : false;
|
|
67
|
+
const files = db.all(
|
|
68
|
+
`SELECT relative_path
|
|
69
|
+
FROM documents
|
|
70
|
+
WHERE 1 = 1
|
|
71
|
+
${db.pathExclusionsFor("documents")}
|
|
72
|
+
ORDER BY relative_path`
|
|
73
|
+
);
|
|
74
|
+
const importers = /* @__PURE__ */ new Set();
|
|
75
|
+
for (const row of files) {
|
|
76
|
+
if (db.isIgnored(row.relative_path)) continue;
|
|
77
|
+
for (const entry of getSourceImports(db, row.relative_path)) {
|
|
78
|
+
if (!entry.sourcePath) continue;
|
|
79
|
+
if (targetFile && normalizePath(entry.sourcePath) !== normalizePath(targetFile)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (targetIsModule) {
|
|
83
|
+
importers.add(row.relative_path);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (entry.kind === "named" && entry.importedName === targetLeaf) {
|
|
87
|
+
importers.add(row.relative_path);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (entry.kind === "namespace" && entry.usedMembers.includes(targetLeaf)) {
|
|
91
|
+
importers.add(row.relative_path);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return [...importers].sort().map((importer) => ({
|
|
96
|
+
symbol: target?.symbol ?? targetLeaf,
|
|
97
|
+
shortName: target ? shortenSymbol(target.symbol) : targetLeaf,
|
|
98
|
+
fromFile: importer
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
function unusedImports(db, filePattern) {
|
|
102
|
+
const importer = resolveIndexedFile(db, filePattern);
|
|
103
|
+
if (!importer) return [];
|
|
104
|
+
const rows = db.all(
|
|
105
|
+
`SELECT gs.symbol, d.relative_path AS imported_in, d.relative_path AS importer
|
|
106
|
+
FROM mentions m
|
|
107
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
108
|
+
JOIN documents d ON c.document_id = d.id
|
|
109
|
+
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
110
|
+
WHERE d.relative_path = ?
|
|
111
|
+
AND m.role = 2
|
|
112
|
+
AND NOT EXISTS (
|
|
113
|
+
SELECT 1
|
|
114
|
+
FROM mentions ref_m
|
|
115
|
+
JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id
|
|
116
|
+
WHERE ref_m.symbol_id = gs.id
|
|
117
|
+
AND ref_m.role != 1
|
|
118
|
+
AND ref_c.document_id = d.id
|
|
119
|
+
)
|
|
120
|
+
ORDER BY d.relative_path, gs.symbol`,
|
|
121
|
+
importer
|
|
122
|
+
);
|
|
123
|
+
const indexedResults = rows.filter((row) => !db.isIgnored(row.importer)).map((r) => ({
|
|
124
|
+
symbol: r.symbol,
|
|
125
|
+
shortName: shortenSymbol(r.symbol),
|
|
126
|
+
importedIn: r.imported_in
|
|
127
|
+
}));
|
|
128
|
+
if (indexedResults.length > 0) {
|
|
129
|
+
return indexedResults;
|
|
130
|
+
}
|
|
131
|
+
return getSourceImports(db, importer).filter((entry) => entry.kind !== "side-effect" && !entry.used).map((entry) => ({
|
|
132
|
+
symbol: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
|
|
133
|
+
shortName: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
|
|
134
|
+
importedIn: importer
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
function renderImportSymbol(importedName, localName, kind) {
|
|
138
|
+
if (kind === "namespace" && importedName === "*" && localName) {
|
|
139
|
+
return `* as ${localName}`;
|
|
140
|
+
}
|
|
141
|
+
if (kind === "default" && localName) {
|
|
142
|
+
return `default as ${localName}`;
|
|
143
|
+
}
|
|
144
|
+
if (kind === "side-effect") {
|
|
145
|
+
return "(side effect import)";
|
|
146
|
+
}
|
|
147
|
+
if (localName && localName !== importedName) {
|
|
148
|
+
return `${importedName} as ${localName}`;
|
|
149
|
+
}
|
|
150
|
+
return importedName;
|
|
151
|
+
}
|
|
152
|
+
function normalizePath(path) {
|
|
153
|
+
return path.replace(/\\/g, "/");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export {
|
|
157
|
+
imports,
|
|
158
|
+
importedBy,
|
|
159
|
+
unusedImports
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=chunk-26DOJ63W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-2UELLEBI.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
testFileExclusionSql
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AXQKUYKF.js";
|
|
4
4
|
import {
|
|
5
5
|
shortenSymbol
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QIXNAB5K.js";
|
|
7
7
|
|
|
8
8
|
// src/queries/wrapper-candidates.ts
|
|
9
9
|
function wrapperCandidates(db, opts) {
|
|
@@ -94,4 +94,4 @@ function wrapperCandidates(db, opts) {
|
|
|
94
94
|
export {
|
|
95
95
|
wrapperCandidates
|
|
96
96
|
};
|
|
97
|
-
//# sourceMappingURL=chunk-
|
|
97
|
+
//# sourceMappingURL=chunk-4JCSOF2O.js.map
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveIndexedPaths
|
|
3
|
+
} from "./chunk-AXQKUYKF.js";
|
|
1
4
|
import {
|
|
2
5
|
shortenSymbol
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QIXNAB5K.js";
|
|
4
7
|
|
|
5
8
|
// src/queries/outline.ts
|
|
6
9
|
function outline(db, filePattern) {
|
|
10
|
+
const resolvedPaths = resolveIndexedPaths(db, filePattern);
|
|
11
|
+
if (resolvedPaths.length === 0) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const placeholders = resolvedPaths.map(() => "?").join(", ");
|
|
7
15
|
const rows = db.all(
|
|
8
16
|
`SELECT gs.symbol, gs.enclosing_symbol, der.start_line, der.end_line
|
|
9
17
|
FROM defn_enclosing_ranges der
|
|
10
18
|
JOIN global_symbols gs ON der.symbol_id = gs.id
|
|
11
19
|
JOIN documents d ON der.document_id = d.id
|
|
12
|
-
WHERE d.relative_path
|
|
20
|
+
WHERE d.relative_path IN (${placeholders})
|
|
13
21
|
${db.symbolNoise}
|
|
14
|
-
ORDER BY der.start_line`,
|
|
15
|
-
|
|
22
|
+
ORDER BY d.relative_path, der.start_line`,
|
|
23
|
+
...resolvedPaths
|
|
16
24
|
);
|
|
17
25
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
18
26
|
const roots = [];
|
|
@@ -40,4 +48,4 @@ function outline(db, filePattern) {
|
|
|
40
48
|
export {
|
|
41
49
|
outline
|
|
42
50
|
};
|
|
43
|
-
//# sourceMappingURL=chunk-
|
|
51
|
+
//# sourceMappingURL=chunk-5OMVSV6E.js.map
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TEST_FILE_PATTERNS,
|
|
3
|
-
testFileMatchSql
|
|
4
|
-
} from "./chunk-ZOGY2V3N.js";
|
|
5
1
|
import {
|
|
6
2
|
shortenSymbol
|
|
7
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QIXNAB5K.js";
|
|
8
4
|
|
|
9
5
|
// src/queries/diff-impact.ts
|
|
10
6
|
import { execFileSync } from "child_process";
|
|
@@ -12,23 +8,17 @@ function diffImpact(db, opts = {}) {
|
|
|
12
8
|
const { base = "HEAD" } = opts;
|
|
13
9
|
let changedFileLines;
|
|
14
10
|
try {
|
|
15
|
-
|
|
16
|
-
encoding: "utf-8",
|
|
17
|
-
cwd: db.config.projectRoot,
|
|
18
|
-
timeout: 1e4
|
|
19
|
-
});
|
|
20
|
-
changedFileLines = stdout.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
|
|
11
|
+
changedFileLines = getChangedFiles(db.config.projectRoot, base);
|
|
21
12
|
} catch {
|
|
22
13
|
return {
|
|
23
14
|
changedFiles: [],
|
|
24
15
|
changedSymbols: [],
|
|
25
16
|
affectedConsumers: [],
|
|
26
|
-
uncoveredSymbols: [],
|
|
27
17
|
summary: {
|
|
28
18
|
totalChangedFiles: 0,
|
|
29
19
|
totalChangedSymbols: 0,
|
|
30
20
|
totalAffectedFiles: 0,
|
|
31
|
-
|
|
21
|
+
note: "Unable to compute git diff."
|
|
32
22
|
}
|
|
33
23
|
};
|
|
34
24
|
}
|
|
@@ -37,12 +27,11 @@ function diffImpact(db, opts = {}) {
|
|
|
37
27
|
changedFiles: [],
|
|
38
28
|
changedSymbols: [],
|
|
39
29
|
affectedConsumers: [],
|
|
40
|
-
uncoveredSymbols: [],
|
|
41
30
|
summary: {
|
|
42
31
|
totalChangedFiles: 0,
|
|
43
32
|
totalChangedSymbols: 0,
|
|
44
33
|
totalAffectedFiles: 0,
|
|
45
|
-
|
|
34
|
+
note: "No changed files found."
|
|
46
35
|
}
|
|
47
36
|
};
|
|
48
37
|
}
|
|
@@ -65,12 +54,11 @@ function diffImpact(db, opts = {}) {
|
|
|
65
54
|
changedFiles: changedFileLines,
|
|
66
55
|
changedSymbols: [],
|
|
67
56
|
affectedConsumers: [],
|
|
68
|
-
uncoveredSymbols: [],
|
|
69
57
|
summary: {
|
|
70
58
|
totalChangedFiles: changedFileLines.length,
|
|
71
59
|
totalChangedSymbols: 0,
|
|
72
60
|
totalAffectedFiles: 0,
|
|
73
|
-
|
|
61
|
+
note: "Changed files are not present in the current SCIP index."
|
|
74
62
|
}
|
|
75
63
|
};
|
|
76
64
|
}
|
|
@@ -85,11 +73,8 @@ function diffImpact(db, opts = {}) {
|
|
|
85
73
|
ORDER BY d.relative_path`,
|
|
86
74
|
...changedDocIds
|
|
87
75
|
);
|
|
88
|
-
const testPatternSql = testFileMatchSql("ref_d", TEST_FILE_PATTERNS);
|
|
89
76
|
const changedSymbols = [];
|
|
90
77
|
const consumerMap = /* @__PURE__ */ new Map();
|
|
91
|
-
const uncoveredSymbols = [];
|
|
92
|
-
let coveredCount = 0;
|
|
93
78
|
for (const sym of syms) {
|
|
94
79
|
const fanInRow = db.get(
|
|
95
80
|
`SELECT COUNT(DISTINCT c.document_id) AS fan_in
|
|
@@ -126,44 +111,41 @@ function diffImpact(db, opts = {}) {
|
|
|
126
111
|
}
|
|
127
112
|
consumerMap.get(consumer.relative_path).add(shortName);
|
|
128
113
|
}
|
|
129
|
-
const hasTest = db.get(
|
|
130
|
-
`SELECT COUNT(*) AS c
|
|
131
|
-
FROM mentions m
|
|
132
|
-
JOIN chunks c ON m.chunk_id = c.id
|
|
133
|
-
JOIN documents ref_d ON c.document_id = ref_d.id
|
|
134
|
-
WHERE m.symbol_id = ?
|
|
135
|
-
AND m.role != 1
|
|
136
|
-
AND (${testPatternSql})`,
|
|
137
|
-
sym.symbol_id
|
|
138
|
-
);
|
|
139
|
-
if (hasTest && hasTest.c > 0) {
|
|
140
|
-
coveredCount++;
|
|
141
|
-
} else {
|
|
142
|
-
uncoveredSymbols.push({
|
|
143
|
-
symbol: sym.symbol,
|
|
144
|
-
shortName,
|
|
145
|
-
file: sym.relative_path
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
114
|
}
|
|
149
115
|
const affectedConsumers = [...consumerMap.entries()].map(([file, symbols]) => ({ file, consumedSymbols: symbols.size })).sort((a, b) => b.consumedSymbols - a.consumedSymbols);
|
|
150
|
-
const totalSymbols = changedSymbols.length;
|
|
151
|
-
const testCoveragePercent = totalSymbols > 0 ? Math.round(coveredCount / totalSymbols * 100) : 0;
|
|
152
116
|
return {
|
|
153
117
|
changedFiles,
|
|
154
118
|
changedSymbols,
|
|
155
119
|
affectedConsumers,
|
|
156
|
-
uncoveredSymbols,
|
|
157
120
|
summary: {
|
|
158
121
|
totalChangedFiles: changedFiles.length,
|
|
159
|
-
totalChangedSymbols:
|
|
160
|
-
totalAffectedFiles: affectedConsumers.length
|
|
161
|
-
testCoveragePercent
|
|
122
|
+
totalChangedSymbols: changedSymbols.length,
|
|
123
|
+
totalAffectedFiles: affectedConsumers.length
|
|
162
124
|
}
|
|
163
125
|
};
|
|
164
126
|
}
|
|
127
|
+
function getChangedFiles(projectRoot, base) {
|
|
128
|
+
const diff = execFileSync("git", ["diff", "--name-only", base], {
|
|
129
|
+
encoding: "utf-8",
|
|
130
|
+
cwd: projectRoot,
|
|
131
|
+
timeout: 1e4
|
|
132
|
+
});
|
|
133
|
+
const staged = execFileSync("git", ["diff", "--name-only", "--cached", base], {
|
|
134
|
+
encoding: "utf-8",
|
|
135
|
+
cwd: projectRoot,
|
|
136
|
+
timeout: 1e4
|
|
137
|
+
});
|
|
138
|
+
const untracked = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
|
|
139
|
+
encoding: "utf-8",
|
|
140
|
+
cwd: projectRoot,
|
|
141
|
+
timeout: 1e4
|
|
142
|
+
});
|
|
143
|
+
return [...new Set(
|
|
144
|
+
[diff, staged, untracked].flatMap((chunk) => chunk.split("\n")).map((line) => line.trim()).filter((line) => line.length > 0)
|
|
145
|
+
)];
|
|
146
|
+
}
|
|
165
147
|
|
|
166
148
|
export {
|
|
167
149
|
diffImpact
|
|
168
150
|
};
|
|
169
|
-
//# sourceMappingURL=chunk-
|
|
151
|
+
//# sourceMappingURL=chunk-7HK5ZLOE.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildFileDepGraph
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AXQKUYKF.js";
|
|
4
4
|
|
|
5
5
|
// src/queries/drift.ts
|
|
6
6
|
import path from "path";
|
|
@@ -10,9 +10,10 @@ function drift(db, opts) {
|
|
|
10
10
|
const symbolRefs = buildSymbolRefGraph(db, scope);
|
|
11
11
|
const results = [];
|
|
12
12
|
for (const [file, deps] of depGraph) {
|
|
13
|
-
if (
|
|
13
|
+
if (shouldSkipDriftFile(file)) continue;
|
|
14
14
|
const referencedFiles = symbolRefs.get(file) ?? /* @__PURE__ */ new Set();
|
|
15
15
|
for (const dep of deps) {
|
|
16
|
+
if (shouldSkipDriftFile(dep)) continue;
|
|
16
17
|
if (!referencedFiles.has(dep)) {
|
|
17
18
|
if (isLikelyTypeOnlyDep(dep)) continue;
|
|
18
19
|
results.push({
|
|
@@ -26,10 +27,11 @@ function drift(db, opts) {
|
|
|
26
27
|
}
|
|
27
28
|
const layerRules = inferLayerRules(depGraph);
|
|
28
29
|
for (const [file, deps] of depGraph) {
|
|
29
|
-
if (
|
|
30
|
-
const fileLayer =
|
|
30
|
+
if (shouldSkipDriftFile(file)) continue;
|
|
31
|
+
const fileLayer = getArchitecturalLayer(file);
|
|
31
32
|
for (const dep of deps) {
|
|
32
|
-
|
|
33
|
+
if (shouldSkipDriftFile(dep)) continue;
|
|
34
|
+
const depLayer = getArchitecturalLayer(dep);
|
|
33
35
|
if (fileLayer === depLayer) continue;
|
|
34
36
|
const violation = layerRules.get(`${fileLayer}->${depLayer}`);
|
|
35
37
|
if (violation === "violation") {
|
|
@@ -53,14 +55,16 @@ function drift(db, opts) {
|
|
|
53
55
|
if (files.length < 3) continue;
|
|
54
56
|
const depFreq = /* @__PURE__ */ new Map();
|
|
55
57
|
for (const file of files) {
|
|
56
|
-
if (
|
|
58
|
+
if (shouldSkipDriftFile(file)) continue;
|
|
57
59
|
for (const dep of depGraph.get(file) ?? []) {
|
|
60
|
+
if (shouldSkipDriftFile(dep)) continue;
|
|
58
61
|
depFreq.set(dep, (depFreq.get(dep) ?? 0) + 1);
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
for (const file of files) {
|
|
62
|
-
if (
|
|
65
|
+
if (shouldSkipDriftFile(file)) continue;
|
|
63
66
|
for (const dep of depGraph.get(file) ?? []) {
|
|
67
|
+
if (shouldSkipDriftFile(dep)) continue;
|
|
64
68
|
if ((depFreq.get(dep) ?? 0) === 1) {
|
|
65
69
|
if (path.dirname(dep) === dir) continue;
|
|
66
70
|
results.push({
|
|
@@ -107,10 +111,12 @@ function inferLayerRules(depGraph) {
|
|
|
107
111
|
const layerEdges = /* @__PURE__ */ new Map();
|
|
108
112
|
const layerSet = /* @__PURE__ */ new Set();
|
|
109
113
|
for (const [file, deps] of depGraph) {
|
|
110
|
-
|
|
114
|
+
if (shouldSkipDriftFile(file)) continue;
|
|
115
|
+
const fromLayer = getArchitecturalLayer(file);
|
|
111
116
|
layerSet.add(fromLayer);
|
|
112
117
|
for (const dep of deps) {
|
|
113
|
-
|
|
118
|
+
if (shouldSkipDriftFile(dep)) continue;
|
|
119
|
+
const toLayer = getArchitecturalLayer(dep);
|
|
114
120
|
if (fromLayer === toLayer) continue;
|
|
115
121
|
layerSet.add(toLayer);
|
|
116
122
|
const key = `${fromLayer}->${toLayer}`;
|
|
@@ -123,13 +129,23 @@ function inferLayerRules(depGraph) {
|
|
|
123
129
|
}
|
|
124
130
|
return rules;
|
|
125
131
|
}
|
|
126
|
-
function
|
|
127
|
-
const
|
|
128
|
-
|
|
132
|
+
function getArchitecturalLayer(filePath) {
|
|
133
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
134
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
135
|
+
if (parts.length <= 1) {
|
|
136
|
+
return "(root)";
|
|
137
|
+
}
|
|
138
|
+
if (parts.length >= 3 && ["src", "lib", "app", "server", "client"].includes(parts[0])) {
|
|
139
|
+
return `${parts[0]}/${parts[1]}`;
|
|
140
|
+
}
|
|
141
|
+
return parts[0];
|
|
129
142
|
}
|
|
130
143
|
function isLikelyTypeOnlyDep(dep) {
|
|
131
144
|
return dep.includes("types") || dep.endsWith(".d.ts");
|
|
132
145
|
}
|
|
146
|
+
function shouldSkipDriftFile(filePath) {
|
|
147
|
+
return isStructuralRole(path.basename(filePath)) || isTestLikePath(filePath);
|
|
148
|
+
}
|
|
133
149
|
function isStructuralRole(basename) {
|
|
134
150
|
if (basename === "index.ts" || basename === "index.js") return true;
|
|
135
151
|
if (basename === "cli.ts" || basename === "main.ts" || basename === "main.rs") return true;
|
|
@@ -137,8 +153,13 @@ function isStructuralRole(basename) {
|
|
|
137
153
|
if (basename === "health.ts" || basename === "health.js") return true;
|
|
138
154
|
return false;
|
|
139
155
|
}
|
|
156
|
+
function isTestLikePath(filePath) {
|
|
157
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
158
|
+
const basename = path.basename(normalized);
|
|
159
|
+
return normalized.includes("/__tests__/") || normalized.includes("/tests/") || normalized.includes("/test/") || /\.(test|spec)\.[A-Za-z0-9]+$/.test(basename) || /_(test|spec)\.[A-Za-z0-9]+$/.test(basename) || /^test[_-]/.test(basename) || /^test\./.test(basename);
|
|
160
|
+
}
|
|
140
161
|
|
|
141
162
|
export {
|
|
142
163
|
drift
|
|
143
164
|
};
|
|
144
|
-
//# sourceMappingURL=chunk-
|
|
165
|
+
//# sourceMappingURL=chunk-7KIMF5PV.js.map
|