scip-query 0.10.11 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/{vendor/scip/LICENSE.scip → LICENSE} +1 -0
- package/README.md +168 -55
- package/dist/augment-vue-worker.js +1 -1
- package/dist/chunk-2VSDXOG5.js +2 -0
- package/dist/chunk-343O6EVV.js +2 -0
- package/dist/chunk-3KDUITBE.js +7 -0
- package/dist/chunk-3T2FNHIU.js +2 -0
- package/dist/chunk-3V6JQQM5.js +2 -0
- package/dist/chunk-5AAAEZ2Z.js +2 -0
- package/dist/chunk-6Q6OFLFQ.js +8 -0
- package/dist/chunk-6XA4LDHY.js +2 -0
- package/dist/chunk-75X52JTA.js +2 -0
- package/dist/{chunk-54KGX7EX.js → chunk-7HB3CZFD.js} +2 -2
- package/dist/chunk-7JZRFDCU.js +2 -0
- package/dist/chunk-7XL7J7PT.js +3 -0
- package/dist/chunk-ALHNAPS2.js +2 -0
- package/dist/{chunk-JATUZIEH.js → chunk-BDRBPG7Y.js} +2 -2
- package/dist/chunk-BN5SXXQS.js +40 -0
- package/dist/chunk-C4ICAIJ4.js +3 -0
- package/dist/{chunk-LSET2TXH.js → chunk-CMHYBXJB.js} +2 -2
- package/dist/{chunk-YWYFU2V3.js → chunk-DRPAQAFM.js} +6 -6
- package/dist/chunk-FERAXG6Y.js +72 -0
- package/dist/chunk-FLJJLSGB.js +2 -0
- package/dist/chunk-FXG3PHVW.js +9 -0
- package/dist/chunk-GCN2P4EJ.js +2 -0
- package/dist/chunk-GHXRVCIY.js +21 -0
- package/dist/chunk-GNG622H3.js +3 -0
- package/dist/chunk-H4LUPLEJ.js +2 -0
- package/dist/{chunk-BASVXNY3.js → chunk-H56MGERE.js} +4 -4
- package/dist/chunk-H7NSJ7L2.js +5 -0
- package/dist/chunk-HINMXZ6J.js +2 -0
- package/dist/chunk-HXXMPYEF.js +2 -0
- package/dist/{chunk-Z3YYR4OS.js → chunk-HZKMEXA3.js} +2 -2
- package/dist/chunk-IFSX6YVU.js +4 -0
- package/dist/chunk-ISLWJ4PY.js +10 -0
- package/dist/chunk-J5WVNZ6O.js +2 -0
- package/dist/chunk-K2HYR5A7.js +3 -0
- package/dist/chunk-K6UI6EBZ.js +2 -0
- package/dist/chunk-KJCDEDQW.js +2 -0
- package/dist/{chunk-Z4HICZGY.js → chunk-KKMOB3OJ.js} +2 -2
- package/dist/{chunk-YWOOQ4FF.js → chunk-KMVGRIO2.js} +2 -2
- package/dist/chunk-LWOOTRHC.js +2 -0
- package/dist/{chunk-EY43NV4M.js → chunk-LZNLRE4X.js} +17 -8
- package/dist/chunk-M2YXL62V.js +23 -0
- package/dist/chunk-MNEJYEHW.js +3 -0
- package/dist/chunk-MTDBHTSF.js +2 -0
- package/dist/{chunk-ZQDIXAF5.js → chunk-N2Z3CU7X.js} +2 -2
- package/dist/chunk-N7PNFLGY.js +2 -0
- package/dist/chunk-NAH5EAZS.js +6 -0
- package/dist/chunk-NBXK32I6.js +2 -0
- package/dist/chunk-NJJ7AS4F.js +2 -0
- package/dist/{chunk-FDEQIPPK.js → chunk-NLMRJ7SI.js} +2 -2
- package/dist/chunk-ODVITBYU.js +26 -0
- package/dist/chunk-ORBRX2QJ.js +2 -0
- package/dist/chunk-P36UR5II.js +2 -0
- package/dist/chunk-PYZZBIEU.js +3 -0
- package/dist/chunk-PZS6J5YG.js +16 -0
- package/dist/{chunk-LM5SHAN4.js → chunk-QARYU7R3.js} +2 -2
- package/dist/chunk-QJ3FK4TB.js +38 -0
- package/dist/chunk-QXGTGE2C.js +35 -0
- package/dist/chunk-QZ4JVECJ.js +2 -0
- package/dist/chunk-R3JY4EZ4.js +102 -0
- package/dist/{chunk-VOYOYC5T.js → chunk-R5336VHZ.js} +2 -2
- package/dist/chunk-RJMXSHKM.js +2 -0
- package/dist/chunk-STBXCPKY.js +5 -0
- package/dist/chunk-T2FQ4GHD.js +9 -0
- package/dist/chunk-TFWDJDGO.js +2 -0
- package/dist/chunk-TG7QSYCJ.js +2 -0
- package/dist/{chunk-FKCGBZAC.js → chunk-TTS75UF2.js} +5 -5
- package/dist/{chunk-BVRS7RKQ.js → chunk-U7I373V4.js} +2 -2
- package/dist/chunk-UIKLA3F5.js +2 -0
- package/dist/{chunk-P753MDDE.js → chunk-UMPNL7T6.js} +2 -2
- package/dist/chunk-URSSPS5H.js +2 -0
- package/dist/chunk-VGMUFW3J.js +2 -0
- package/dist/chunk-VXTNADIW.js +18 -0
- package/dist/chunk-VYF5HA76.js +2 -0
- package/dist/chunk-WFGOH2UI.js +43 -0
- package/dist/chunk-WGA5BBTA.js +4 -0
- package/dist/chunk-WIBFXSYB.js +6 -0
- package/dist/chunk-WPSS37EW.js +2 -0
- package/dist/chunk-WQHWIVA7.js +3 -0
- package/dist/chunk-WS3Z6W3M.js +65 -0
- package/dist/chunk-WXVGNFAO.js +2 -0
- package/dist/{chunk-6LJHXREW.js → chunk-WZLPXFZU.js} +2 -2
- package/dist/chunk-X4O6K47U.js +2 -0
- package/dist/chunk-X6OGDTQH.js +2 -0
- package/dist/chunk-XEMQUN3Z.js +20 -0
- package/dist/{chunk-7B6LP46R.js → chunk-XHWLNQVZ.js} +2 -2
- package/dist/chunk-XMR747CP.js +2 -0
- package/dist/chunk-Y6L4LXPG.js +2 -0
- package/dist/chunk-YCPASUCX.js +2 -0
- package/dist/chunk-YZXV3CU3.js +60 -0
- package/dist/chunk-ZEKBR4OK.js +10 -0
- package/dist/chunk-ZMGBWSFZ.js +2 -0
- package/dist/cli.js +462 -274
- package/dist/{config-types-BDIWAYzr.d.ts → config-types-BrHl3Bge.d.ts} +61 -1
- package/dist/{db-Djj3Nqrb.d.ts → db-_Bdx0E1W.d.ts} +1 -1
- package/dist/diff-gate-types-CG2YQ_ei.d.ts +4 -0
- package/dist/{frontend-behavior-evidence-BxKpKWUu.d.ts → frontend-behavior-evidence-EfM4_9bc.d.ts} +1 -1
- package/dist/{health-D5J42g4D.d.ts → health-BEZ1Rt0S.d.ts} +54 -2
- package/dist/index.d.ts +10 -70
- package/dist/index.js +2 -2
- package/dist/postinstall.js +1 -4
- package/dist/queries/affected.d.ts +2 -2
- package/dist/queries/affected.js +1 -1
- package/dist/queries/bottlenecks.d.ts +2 -2
- package/dist/queries/bottlenecks.js +1 -1
- package/dist/queries/by-kind.d.ts +2 -2
- package/dist/queries/by-kind.js +1 -1
- package/dist/queries/call-graph.d.ts +2 -2
- package/dist/queries/call-graph.js +1 -1
- package/dist/queries/change-surface.d.ts +2 -2
- package/dist/queries/change-surface.js +1 -1
- package/dist/queries/cleanup-plan.d.ts +2 -2
- package/dist/queries/cleanup-plan.js +1 -1
- package/dist/queries/co-change.d.ts +12 -2
- package/dist/queries/co-change.js +1 -1
- package/dist/queries/code.d.ts +2 -2
- package/dist/queries/code.js +1 -1
- package/dist/queries/complexity-hotspots.d.ts +7 -3
- package/dist/queries/complexity-hotspots.js +1 -1
- package/dist/queries/complexity.d.ts +42 -4
- package/dist/queries/complexity.js +1 -1
- package/dist/queries/convergence.d.ts +2 -2
- package/dist/queries/convergence.js +1 -1
- package/dist/queries/coupling.d.ts +2 -2
- package/dist/queries/coupling.js +1 -1
- package/dist/queries/cycles.d.ts +12 -3
- package/dist/queries/cycles.js +1 -1
- package/dist/queries/dataflow.d.ts +2 -2
- package/dist/queries/dataflow.js +1 -1
- package/dist/queries/dead.d.ts +3 -3
- package/dist/queries/dead.js +1 -1
- package/dist/queries/deep-chains.d.ts +2 -2
- package/dist/queries/deep-chains.js +1 -1
- package/dist/queries/deps.d.ts +2 -2
- package/dist/queries/deps.js +1 -1
- package/dist/queries/diff-gate.d.ts +65 -8
- package/dist/queries/diff-gate.js +1 -1
- package/dist/queries/diff-impact.d.ts +21 -3
- package/dist/queries/diff-impact.js +1 -1
- package/dist/queries/doc-drift.d.ts +29 -2
- package/dist/queries/doc-drift.js +1 -1
- package/dist/queries/drift.d.ts +15 -3
- package/dist/queries/drift.js +1 -1
- package/dist/queries/duplicate-bodies.d.ts +55 -0
- package/dist/queries/duplicate-bodies.js +2 -0
- package/dist/queries/extract-candidates.d.ts +2 -2
- package/dist/queries/extract-candidates.js +1 -1
- package/dist/queries/fan.d.ts +2 -2
- package/dist/queries/fan.js +1 -1
- package/dist/queries/files.d.ts +4 -3
- package/dist/queries/files.js +1 -1
- package/dist/queries/health.d.ts +3 -3
- package/dist/queries/health.js +1 -1
- package/dist/queries/hierarchy.d.ts +2 -2
- package/dist/queries/hierarchy.js +1 -1
- package/dist/queries/hotspots.d.ts +2 -2
- package/dist/queries/hotspots.js +1 -1
- package/dist/queries/imports.d.ts +2 -2
- package/dist/queries/imports.js +1 -1
- package/dist/queries/incomplete-migration.d.ts +3 -2
- package/dist/queries/incomplete-migration.js +1 -1
- package/dist/queries/index.d.ts +12 -7
- package/dist/queries/index.js +1 -1
- package/dist/queries/isolated.d.ts +2 -2
- package/dist/queries/isolated.js +1 -1
- package/dist/queries/locality-candidates.d.ts +2 -2
- package/dist/queries/locality-candidates.js +1 -1
- package/dist/queries/members.d.ts +2 -2
- package/dist/queries/members.js +1 -1
- package/dist/queries/methods.d.ts +2 -2
- package/dist/queries/methods.js +1 -1
- package/dist/queries/outline.d.ts +2 -2
- package/dist/queries/outline.js +1 -1
- package/dist/queries/passthrough-candidates.d.ts +11 -3
- package/dist/queries/passthrough-candidates.js +1 -1
- package/dist/queries/plan-context.d.ts +3 -2
- package/dist/queries/plan-context.js +1 -1
- package/dist/queries/react-component-duplicates.d.ts +7 -2
- package/dist/queries/react-component-duplicates.js +1 -1
- package/dist/queries/react-hook-candidates.d.ts +3 -3
- package/dist/queries/react-hook-candidates.js +1 -1
- package/dist/queries/react-large-component-pressure.d.ts +2 -2
- package/dist/queries/react-large-component-pressure.js +1 -1
- package/dist/queries/recent-duplicates.d.ts +2 -2
- package/dist/queries/recent-duplicates.js +1 -1
- package/dist/queries/redundant-reexports.d.ts +2 -2
- package/dist/queries/redundant-reexports.js +1 -1
- package/dist/queries/refs.d.ts +2 -2
- package/dist/queries/refs.js +1 -1
- package/dist/queries/self-audit.d.ts +9 -4
- package/dist/queries/self-audit.js +1 -1
- package/dist/queries/similar-chains.d.ts +2 -2
- package/dist/queries/similar-chains.js +1 -1
- package/dist/queries/similar-files.d.ts +2 -2
- package/dist/queries/similar-files.js +1 -1
- package/dist/queries/similar-signatures.d.ts +17 -10
- package/dist/queries/similar-signatures.js +1 -1
- package/dist/queries/similar.d.ts +85 -17
- package/dist/queries/similar.js +1 -1
- package/dist/queries/slice.d.ts +2 -2
- package/dist/queries/slice.js +1 -1
- package/dist/queries/stale-abstractions.d.ts +2 -2
- package/dist/queries/stale-abstractions.js +1 -1
- package/dist/queries/stats.d.ts +2 -2
- package/dist/queries/surface.d.ts +2 -2
- package/dist/queries/surface.js +1 -1
- package/dist/queries/symbols.d.ts +2 -2
- package/dist/queries/symbols.js +1 -1
- package/dist/queries/system.d.ts +2 -2
- package/dist/queries/system.js +1 -1
- package/dist/queries/trace.d.ts +2 -2
- package/dist/queries/trace.js +1 -1
- package/dist/queries/twin-ab.d.ts +55 -0
- package/dist/queries/twin-ab.js +2 -0
- package/dist/queries/twin-drift.d.ts +97 -0
- package/dist/queries/twin-drift.js +2 -0
- package/dist/queries/unused-imports.d.ts +2 -2
- package/dist/queries/unused-imports.js +1 -1
- package/dist/queries/unused-params.d.ts +2 -2
- package/dist/queries/unused-params.js +1 -1
- package/dist/queries/vue-component-duplicates.d.ts +7 -2
- package/dist/queries/vue-component-duplicates.js +1 -1
- package/dist/queries/vue-composable-candidates.d.ts +3 -3
- package/dist/queries/vue-composable-candidates.js +1 -1
- package/dist/queries/vue-large-view-pressure.d.ts +6 -2
- package/dist/queries/vue-large-view-pressure.js +1 -1
- package/dist/queries/wrapper-candidates.d.ts +2 -2
- package/dist/queries/wrapper-candidates.js +1 -1
- package/dist/reindex-worker.js +9 -9
- package/dist/reindex.d.ts +30 -4
- package/dist/reindex.js +19 -19
- package/dist/runtime.d.ts +12 -6
- package/dist/runtime.js +2 -2
- package/dist/{scip-cli-CnK9Va4O.d.ts → scip-cli-C7cg4ZHR.d.ts} +1 -1
- package/dist/symbol-types-DaoeXKUt.d.ts +66 -0
- package/docs/AGENT_GUIDE.md +20 -18
- package/docs/AI_FAILURE_MODES.md +36 -13
- package/docs/API.md +1 -1
- package/docs/COMMAND_REFERENCE.md +57 -14
- package/docs/DETECTOR_GUIDE.md +20 -3
- package/docs/REGEX_POLICY.md +34 -0
- package/docs/analyzer-inventory.md +48 -3
- package/docs/analyzer-validation-ledger.md +41 -6
- package/package.json +23 -7
- package/scripts/build-scip-windows.mjs +10 -7
- package/scripts/evidence-product-contract.mjs +197 -0
- package/skills/_shared/SKILL.md +243 -0
- package/skills/_shared/agents/openai.yaml +4 -0
- package/skills/scip-api-impact/SKILL.md +55 -71
- package/skills/scip-claim-audit/SKILL.md +105 -0
- package/skills/scip-claim-audit/agents/openai.yaml +4 -0
- package/skills/scip-cleanup-audit/SKILL.md +122 -0
- package/skills/scip-cleanup-audit/agents/openai.yaml +4 -0
- package/skills/scip-cleanup-improve/SKILL.md +84 -0
- package/skills/scip-cleanup-improve/agents/openai.yaml +4 -0
- package/skills/scip-concrete-plan/SKILL.md +181 -0
- package/skills/scip-concrete-plan/agents/openai.yaml +4 -0
- package/skills/scip-conductor/SKILL.md +133 -0
- package/skills/scip-conductor/agents/openai.yaml +4 -0
- package/skills/scip-debug/SKILL.md +60 -58
- package/skills/scip-diagram/SKILL.md +64 -94
- package/skills/scip-directory-architecture/SKILL.md +65 -107
- package/skills/scip-doc-reconcile/SKILL.md +56 -67
- package/skills/scip-explore/SKILL.md +78 -210
- package/skills/scip-hyper-optimization/SKILL.md +124 -198
- package/skills/scip-integrity-audit/SKILL.md +103 -0
- package/skills/scip-integrity-audit/agents/openai.yaml +4 -0
- package/skills/scip-language-playbook/SKILL.md +56 -326
- package/skills/scip-maintainability/SKILL.md +80 -219
- package/skills/scip-probe-reachability/SKILL.md +92 -0
- package/skills/scip-probe-reachability/agents/openai.yaml +4 -0
- package/skills/scip-query/SKILL.md +108 -124
- package/skills/scip-react-maintainability/SKILL.md +64 -82
- package/skills/scip-setup/SKILL.md +121 -0
- package/skills/scip-setup/agents/openai.yaml +4 -0
- package/skills/scip-tla-model-system/SKILL.md +138 -0
- package/skills/scip-tla-model-system/agents/openai.yaml +4 -0
- package/skills/scip-triage-issue/SKILL.md +53 -41
- package/skills/scip-twin-drift/SKILL.md +107 -0
- package/skills/scip-twin-drift/agents/openai.yaml +4 -0
- package/skills/scip-verify/SKILL.md +70 -88
- package/skills/scip-vue-maintainability/SKILL.md +67 -94
- package/dist/chunk-2KHTSEIL.js +0 -102
- package/dist/chunk-3VD3JMK2.js +0 -2
- package/dist/chunk-4UZO3XCV.js +0 -35
- package/dist/chunk-5GOLFJEO.js +0 -8
- package/dist/chunk-5OST6GYB.js +0 -2
- package/dist/chunk-65AU3HFZ.js +0 -2
- package/dist/chunk-6GN7FXCH.js +0 -2
- package/dist/chunk-6IR2AOBM.js +0 -7
- package/dist/chunk-6JRV4MY2.js +0 -23
- package/dist/chunk-6QSOCTZT.js +0 -18
- package/dist/chunk-72KY2ZFO.js +0 -2
- package/dist/chunk-7GO4EQF5.js +0 -2
- package/dist/chunk-7IVSJJZU.js +0 -7
- package/dist/chunk-7TWLSZK5.js +0 -2
- package/dist/chunk-A536TEU4.js +0 -3
- package/dist/chunk-AVWPHM2Q.js +0 -4
- package/dist/chunk-B32FX5KB.js +0 -2
- package/dist/chunk-B6MJ5VQV.js +0 -2
- package/dist/chunk-BFXPG2VN.js +0 -2
- package/dist/chunk-BSN22NRK.js +0 -9
- package/dist/chunk-BZ53S4ZN.js +0 -2
- package/dist/chunk-C5CTSJ6X.js +0 -6
- package/dist/chunk-CO5GJRP7.js +0 -2
- package/dist/chunk-CW5YFOCP.js +0 -5
- package/dist/chunk-DS6QEB3G.js +0 -5
- package/dist/chunk-E35O7UCB.js +0 -2
- package/dist/chunk-EXDQ35NN.js +0 -2
- package/dist/chunk-FAYI6KZ5.js +0 -2
- package/dist/chunk-FFVIFETB.js +0 -2
- package/dist/chunk-FG4NT6VY.js +0 -2
- package/dist/chunk-FXNWFMKW.js +0 -25
- package/dist/chunk-G5UPYQGL.js +0 -4
- package/dist/chunk-GQBMH2TQ.js +0 -2
- package/dist/chunk-GRJY65YT.js +0 -2
- package/dist/chunk-HF25DFSC.js +0 -3
- package/dist/chunk-HHN2B5KA.js +0 -2
- package/dist/chunk-IHUETYFW.js +0 -2
- package/dist/chunk-JCLDUKT6.js +0 -38
- package/dist/chunk-JGN2ZFJR.js +0 -2
- package/dist/chunk-JM72FNGA.js +0 -2
- package/dist/chunk-JME7OWD3.js +0 -2
- package/dist/chunk-KDFONWTW.js +0 -40
- package/dist/chunk-LPL4MA6R.js +0 -2
- package/dist/chunk-LZHUWKGD.js +0 -2
- package/dist/chunk-M4COR2H6.js +0 -2
- package/dist/chunk-NOJAM5ZV.js +0 -21
- package/dist/chunk-O6ZH6C6Y.js +0 -2
- package/dist/chunk-OBGRLXWF.js +0 -3
- package/dist/chunk-OLTESY4K.js +0 -3
- package/dist/chunk-ONPCQ2PM.js +0 -6
- package/dist/chunk-P4KYUPBD.js +0 -4
- package/dist/chunk-P5RYBRIO.js +0 -4
- package/dist/chunk-P7AL7Y37.js +0 -2
- package/dist/chunk-PFOCOG57.js +0 -2
- package/dist/chunk-QLAUCRDJ.js +0 -2
- package/dist/chunk-QPU7EXAW.js +0 -2
- package/dist/chunk-QYB5P7GL.js +0 -2
- package/dist/chunk-RNM6LMCF.js +0 -2
- package/dist/chunk-RVWSAMTT.js +0 -2
- package/dist/chunk-TK7O5ER5.js +0 -3
- package/dist/chunk-TQ5W2H3S.js +0 -4
- package/dist/chunk-USPV3T5K.js +0 -2
- package/dist/chunk-UUBMFL3F.js +0 -59
- package/dist/chunk-VCQYSG2M.js +0 -10
- package/dist/chunk-VUKC6F77.js +0 -20
- package/dist/chunk-W2CBNBEL.js +0 -71
- package/dist/chunk-W6BVEKYC.js +0 -3
- package/dist/chunk-WUCEKFQC.js +0 -3
- package/dist/chunk-XUGQU7PM.js +0 -41
- package/dist/chunk-Y5NBHMQX.js +0 -2
- package/dist/chunk-YCOFCT4B.js +0 -2
- package/dist/chunk-YZA6PPZL.js +0 -3
- package/skills/concrete-plan/SKILL.md +0 -372
- package/skills/concrete-plan/agents/openai.yaml +0 -4
- package/skills/scip-adoption/SKILL.md +0 -122
- package/skills/scip-adoption/agents/openai.yaml +0 -4
- package/skills/scip-ai-cleanup/SKILL.md +0 -153
- package/skills/scip-ai-cleanup/agents/openai.yaml +0 -4
- package/skills/scip-debloat/SKILL.md +0 -439
- package/skills/scip-debloat/agents/openai.yaml +0 -4
- package/skills/scip-health-audit/SKILL.md +0 -162
- package/skills/scip-health-audit/agents/openai.yaml +0 -4
- package/skills/scip-health-improve/SKILL.md +0 -155
- package/skills/scip-health-improve/agents/openai.yaml +0 -4
- package/skills/scip-query-setup/SKILL.md +0 -170
- package/skills/scip-query-setup/agents/openai.yaml +0 -3
- package/vendor/scip/README.md +0 -6
- package/vendor/scip/win32-arm64/scip.exe +0 -0
- package/vendor/scip/win32-x64/scip.exe +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `scip-query` are documented here. This file starts at 0.11.0; everything below covers behavior changes made since the 0.10.12 release.
|
|
4
|
+
|
|
5
|
+
## [0.11.0]
|
|
6
|
+
|
|
7
|
+
### Breaking (one-way doors — read before upgrading)
|
|
8
|
+
|
|
9
|
+
- **`npm install` no longer installs anything beyond the package itself.** Postinstall used to symlink skills into your home directory and could shell out to `brew`/`go install` for missing toolchains. It now prints exactly one line — `scip-query installed -- run 'scip-query setup' in a repo to enable skills, hooks, and the index.` — and does nothing else. Run `scip-query setup` explicitly in a project to get skills, hooks, and a first index.
|
|
10
|
+
- **Project hooks default to an untracked file.** `scip-query setup` (and `setup-hooks`) now write Claude Code hooks to `.claude/settings.local.json` instead of the tracked `.claude/settings.json`, so a teammate's agent tooling preferences no longer land in git by default. Run `setup-hooks --shared` to opt back into the tracked file. `setup-hooks --remove` writes a decline tombstone so a later `setup` won't silently re-add hooks you removed; `--force` overrides it.
|
|
11
|
+
- **Suppression IDs use a new stable hash.** `.scipquery.json` suppression `id`s are now derived from `(check, symbol, file)` only, not the full match set, so an unrelated new similar function elsewhere no longer silently un-suppresses an accepted finding. Existing legacy-format IDs still match (dual-matching) — nothing in your config needs to change today — but `config-validate` now prints an info diagnostic naming the stable replacement for each legacy entry.
|
|
12
|
+
- **Windows no longer ships a vendored `scip.exe`.** The 39 MB vendored binary is gone. Windows installs now receive the binary through `scip-query-scip-windows`, a universal (x64 + arm64) os-gated optional npm dependency fetched only on Windows; resolution order is PATH → `SCIP_QUERY_SCIP_BIN` env → sidecar package → printed instructions. Publishing the main package auto-builds and auto-publishes the sidecar (`prepublishOnly`). Set `SCIP_QUERY_SCIP_BIN` to a local `scip.exe` to override.
|
|
13
|
+
- **`convergence` is deprecated.** Use `similar <symbol1> <symbol2> --plan` instead. `convergence` still works (as a thin alias) but is not the documented path going forward.
|
|
14
|
+
- **`drift`'s pattern-deviation channel is now opt-in.** The "only sibling in this directory depends on X" noise channel used to run by default; it now requires `--patterns`. `drift` also gained `-n/--limit <n>` (default 50) — previously unbounded output could reach hundreds of KB on a large repo. Unused-import and layer-violation findings are unaffected and still run by default.
|
|
15
|
+
- **`doc-reference` findings are now split by citation granularity.** Only line-anchored citations (`file.ts:123`) or citations of a file that was deleted/renamed still block `diff-gate`. A bare file-mention citation (no line anchor) is now advisory: it prints and is suppressible but never fails the gate by itself.
|
|
16
|
+
- **`tla verify` groups findings by default.** Human-mode output now prints findings grouped by `(category, modelElement)` with a count and up to 3 exemplars per group, instead of every finding individually — one Vega-scale model previously produced 10,724 lines of output from a handful of root causes. Pass `--full` to get the old ungrouped behavior. `--json` is unaffected except for a new `findingGroups` summary alongside the still-complete `findings` array.
|
|
17
|
+
|
|
18
|
+
### Notable (new capabilities)
|
|
19
|
+
|
|
20
|
+
- **New commands:** `duplicate-bodies` (finds byte-identical small callable bodies across files — the "same helper copy-pasted into seven files" shape `similar`'s shape-based scoring is too coarse to catch), `twin-drift` (finds same-name or near-name functions across files whose bodies have diverged — a signal one side got a fix the other never received), `uninstall` (reverses `install-skills`/`setup-hooks`, with `--dry-run`), and the `tla` model-checking family: `tla scaffold` (draft a TLA+ spec/config/mapping from indexed code), `tla instrument` (generate a trace recorder plus wiring sites), `tla trace-check` (prove a recorded execution is a legal model transition via the real TLC checker), and `tla fetch-tools` (download the sha256-pinned `tla2tools.jar`). This release also adds `tla verify`/`trace-check --timeout-ms` and `tla verify --full`.
|
|
21
|
+
- **`tla verify` actually verifies now.** Declared `reads` are checked against a static scan (not just parsed and ignored); variable/action referents that resolve to a type instead of a value produce a hard error; every waiver requires a reason and is counted in the output; the checker's config `INVARIANT`s are cross-checked against the mapping's declared invariants. A PASS with unwaived findings is no longer possible, and the proof summary is itemized (`writes: N verified, M waived`, etc.) instead of a single overclaiming sentence.
|
|
22
|
+
- **Two new `diff-gate` checks:** `twin-partner` (advisory — a changed symbol has a same-name twin elsewhere that this diff left untouched) and `coverage-contract` (a configured `.scipquery.json` `coverageContracts` entry drifted from its ground-truth source — enumeration rot).
|
|
23
|
+
- **Three new lens skills:** `scip-twin-drift`, `scip-claim-audit` (classify whether an "available"/"verified"/"safe"/"PASS" claim is derived from a real check or merely asserted), and `scip-probe-reachability` (prove whether a parser/AST branch is actually reachable by running the real parser on minimal inputs).
|
|
24
|
+
- **Skill set consolidated.** `scip-adoption`/`scip-query-setup` merged into `scip-setup`; the four-skill cleanup family collapsed into `scip-cleanup-audit` (report-only, three modes) and `scip-cleanup-improve` (autonomous fixing loop); every workflow now closes out through a single `scip-verify` skill instead of duplicated inline postchecks.
|
|
25
|
+
- **Skill set standardized on the `scip-` prefix.** `concrete-plan` → `scip-concrete-plan` and `tla-model-system` → `scip-tla-model-system`; `install-skills` prunes the old symlinked names automatically on the next run, no manual cleanup needed. `_shared` is the one intentional exception (reference infrastructure loaded by other skills, not user-invoked).
|
|
26
|
+
- **New skill: `scip-conductor`.** Bundles the previously user-global-only "conduct a multi-phase program" method (plan, delegate, verify handoffs, close, with pre-registered benchmarks) as a first-class installed skill, routed from the `scip-query` router with a tie-break against `scip-concrete-plan` (one change vs. a program of changes with delegation).
|
|
27
|
+
- **README documents every bundled skill.** A new "Bundled skills" table in README.md lists all 25 installed skills with a one-line essential-difference summary each, explicitly disambiguating the clusters that are easy to confuse (`scip-concrete-plan` vs `scip-conductor`, `scip-cleanup-audit` vs `scip-cleanup-improve`, `scip-verify` vs `scip-integrity-audit` vs `scip-maintainability` vs `scip-twin-drift`, `scip-directory-architecture` vs `scip-maintainability`).
|
|
28
|
+
- **`analysisBudget` JSON disclosure extended to every budgeted command.** Previously only `diff-gate --json` disclosed when a large-index scan cap engaged. Now `change-surface`, `incomplete-migration`, `dataflow`, `slice`, `plan-context`, `complexity`, `dead`, `extract-candidates`, `locality-candidates`, `cleanup-plan`, `recent-duplicates`, and every command built on the generic list/report/table command builders (`refs`, `imports`, `trace`, `similar`, `drift`, `isolated`, `unused-params`, and more) include an `analysisBudget` field in their JSON envelope whenever a cap engaged (omitted otherwise) — a reduced-coverage pass no longer presents as a full one to a JSON consumer.
|
|
29
|
+
- **Every command's evidence tier is now architectural, not per-command artisanal.** Human output prints a heuristic disclaimer and `--json` stamps an `evidence: "graph-fact" | "heuristic" | "mixed"` field for every command, driven by the descriptor registry rather than five different disconnected mechanisms. "Safe to delete" language is gone everywhere except compiler-verified (tier-4) output — cleanup findings now read "deletion candidates; confirm with cleanup-plan --verify."
|
|
30
|
+
- **`cleanup-plan --verify` reads the real checker exit status.** The banner is now `VERIFIED (<oracle>)` (naming `tsc`, `go build`, `ruff`, `python-compileall`, `clj-kondo`, or `cargo check`) instead of a blanket "COMPILER-VERIFIED", and it discloses when working-tree files outside the plan were dirty at verification time.
|
|
31
|
+
- **`finding-outcome ledger` and precision reporting.** `diff-gate` now tracks each check's resolution/suppression rate over time; low-precision checks surface a nudge in `--hook` mode, and `health --json` reports `detectorPrecision` per check.
|
|
32
|
+
- **Snapshot-doc policy.** `.scipquery.json`'s `docs.snapshotPaths` globs (or an inline `<!-- scip-query: snapshot -->` marker) exempt dated ledger/report docs from `doc-reference`/`doc-drift` findings, eliminating a recurring wall of false doc-drift positives on append-only docs.
|
|
33
|
+
- **Health dogfood: 97 → 100.** The layer policy gained `runtime → tla` (the CLI layer importing its own query module, the established pattern) and `src/core` is now a legal dependency for `source`, `semantic`, `runtime`, `tla`, and `language-parsers`. `escapeRegex` moved to a new zero-dependency `src/core/regex-utils.ts`, restoring the documented invariant that `src/semantic` never imports `src/source`. `binaryAvailable` moved to `src/core/command-availability.ts`; the shared download/checksum/cache primitive both `tla fetch-tools` and the Windows `scip.exe` fetcher needed now lives in `src/core/verified-binary-fetch.ts`, letting three prior "we'd extract this but `src/core` isn't reachable yet" suppressions be deleted outright. Four duplicate-body pairs were consolidated into shared helpers; three were left as documented intentional variation (React/Vue parity functions, echo/baseline remediation text) rather than force-merged.
|
|
34
|
+
|
|
35
|
+
### Fixes (accuracy / false-positive)
|
|
36
|
+
|
|
37
|
+
- **Three false-dead archetypes fixed.** Symbols consumed only via `import type` across a `tsconfig` path alias are no longer reported dead. pnpm-workspace cross-package consumers are now resolved via a new workspace-package resolver (this also fixed a real bug — `fanInBySymbolId.get(id) === 0` treated an *absent* symbol the same as a zero-reference one, suppressing semantic enrichment broadly, not just for the workspace case). Vue `<script setup>` composable consumers were verified already correct and gained a regression fixture. Where the remaining gap couldn't be closed this release (an ambiguous leaf name across an unresolved barrel re-export hop), the finding is now labeled `unconfirmed` instead of asserted `dead`.
|
|
38
|
+
- **`diff-gate` fails closed.** A git-diff-unavailable condition (diff too large for the exec buffer, a bad `--base`, or a git error) now exits nonzero having run zero checks, instead of silently passing.
|
|
39
|
+
- **`doc-drift` epoch-0 timestamp bug fixed.** A doc whose only commit touched it as part of a >50-file bulk sweep now falls back to file mtime instead of being reported as "last changed at the Unix epoch."
|
|
40
|
+
- **SANY XML export was silently dead code.** `-o <path>` on the SANY invocation meant "offline mode," not "output path" — the real-parser XML export path never actually ran. Fixed the invocation and rewrote the XML grammar parser against real `tla2tools` v1.8.0 output.
|
|
41
|
+
- **`tla verify`/`trace-check` timeout misclassification fixed.** `spawnSync`'s own timeout kill has no `ETIMEDOUT` error shape — only `signal: 'SIGTERM'` — so a genuine timeout was previously reported as an ordinary `failed` run. A SIGTERM landing at or after the requested `timeoutMs` boundary is now classified `timed-out`.
|
|
42
|
+
- **Calibration retunes from external repo validation:** `duplicate-bodies`' default `--min-loc` raised from 1 to 3 (kills 1-line forwarding-stub noise); `twin-drift` excludes synthetic constructor-style leaves and test-only groups; `co-change` exempts locale/i18n sibling resource files from hidden-coupling findings; `stale-abstractions`/`wrapper-candidates` gained an explicit false-positive-rate caveat and were demoted from the default `cleanup-audit` sweep to an opt-in deep-dive.
|
|
43
|
+
- Assorted smaller fixes: parameterized SQL in a scope filter (injection-shaped hygiene, no known exploit), fan-in/hotspot queries no longer counting a symbol's own defining file as a consumer, AST-based cyclomatic-complexity counting, nested `.gitignore` support, and Vue single-file-component script extraction unified across the codebase.
|
|
44
|
+
|
|
45
|
+
[0.11.0]: https://github.com/PlunderStruck/scip-query/releases/tag/v0.11.0
|
package/README.md
CHANGED
|
@@ -20,29 +20,40 @@
|
|
|
20
20
|
<a href="https://www.apache.org/licenses/LICENSE-2.0"><img alt="License" src="https://img.shields.io/npm/l/scip-query.svg"></a>
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
|
-
`scip-query` is a TypeScript CLI and npm package
|
|
23
|
+
`scip-query` gives AI coding agents compiler-grade evidence about your repository and mechanical gates on what they produce. Under the hood it is a TypeScript CLI and npm package built on SCIP indexes, git history, language-aware source analysis, and your repository's own checks.
|
|
24
24
|
|
|
25
25
|
Agents are effective at editing the code in front of them. They are less reliable at preserving a whole-repository model across a long task: they miss existing helpers, plan from partial context, migrate only some call sites, overlook files coupled only by history, and declare a diff finished while it still adds duplication, dead code, or stale documentation.
|
|
26
26
|
|
|
27
27
|
`scip-query` gives them a repeatable operating loop: map the target and its blast radius, build a concrete plan from repository evidence, check for reuse before adding a concept, detect unfinished migrations and hidden coupling, and gate the final diff. It does not replace the compiler, tests, or review; it makes structural evidence and repository checks easy for agents to invoke and report.
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## How Agents Use It
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
|
38
|
-
|
|
|
31
|
+
Two layers, wired by `scip-query setup`:
|
|
32
|
+
|
|
33
|
+
**Ambient** — no invocation required. Session-start hooks supply index state and routing context; the Stop-hook / pre-commit **diff gate** checks every finished diff for echoes of existing code, unfinished migrations, missing co-change partners, stale doc citations, and new dead code — and feeds findings back to the agent.
|
|
34
|
+
|
|
35
|
+
**Invoked** — the agent routes work through skills, each carrying its own short command list so it never navigates the full CLI:
|
|
36
|
+
|
|
37
|
+
| Phase | Skill | Commands underneath (also usable directly) |
|
|
38
|
+
| --------- | -------------------------------------------------------- | ----------------------------------------------- |
|
|
39
|
+
| Orient | `scip-explore` | `system`, `trace`, `plan-context`, `call-graph` |
|
|
40
|
+
| Plan | `scip-concrete-plan` (one change) · `scip-conductor` (a program) | `plan-context`, `change-surface`, `co-change` |
|
|
41
|
+
| Reuse | (taught in-loop by the planning skills) | `similar`, `duplicate-bodies`, `recent-duplicates` |
|
|
42
|
+
| Implement | your agent + the post-change check for the change type | `incomplete-migration`, `unused-params`, `co-change` |
|
|
43
|
+
| Verify | `scip-verify` (closeout) + the ambient diff gate | `diff-impact`, `diff-gate`, `health --baseline` |
|
|
44
|
+
| Clean up | `scip-cleanup-audit` → `scip-cleanup-improve` | `cleanup-plan --verify`, `dead`, `twin-drift` |
|
|
45
|
+
|
|
46
|
+
Interrogation lenses go deeper on demand: `scip-integrity-audit` ("is this implementation real?"), `scip-twin-drift`, `scip-claim-audit`, `scip-probe-reachability`, and `scip-maintainability`. The full map with essential differences is in [Bundled skills](#bundled-skills); every command remains directly invocable for humans and scripts.
|
|
39
47
|
|
|
40
48
|
React and Vue repositories get additional framework-aware checks for repeated component/template structure, hook/composable behavior, and large-component or large-view pressure. These extend the same reuse and completion workflow; the core graph, history, planning, cleanup, and diff-gate commands are not frontend-specific.
|
|
41
49
|
|
|
42
50
|
## Install
|
|
43
51
|
|
|
52
|
+
`npm install` only installs the package — it does not touch your home directory, your shell config, or any agent's skill/hook setup. Every write happens explicitly, when you ask for it:
|
|
53
|
+
|
|
44
54
|
```bash
|
|
45
55
|
npm install -g scip-query@latest
|
|
56
|
+
scip-query setup # opt-in: skills, project hooks, first index, health dossier
|
|
46
57
|
scip-query check-deps
|
|
47
58
|
scip-query reindex
|
|
48
59
|
```
|
|
@@ -99,11 +110,15 @@ Heuristic findings are candidates for inspection, not proof of equivalence or ba
|
|
|
99
110
|
|
|
100
111
|
Graph navigation works through supported [SCIP](https://github.com/sourcegraph/scip) indexers. Higher-confidence augmentation and verification vary by language and project toolchain. TypeScript currently has the richest semantic augmentation. React and Vue add built-in framework-aware maintainability checks on top of the core workflow.
|
|
101
112
|
|
|
113
|
+
Clojure projects are indexed through `scip-clojure`. Source fallback adds namespace imports, callable/callsite evidence, and protocol/record member evidence for `.clj`, `.cljs`, and `.cljc` files. When the project has `clj-kondo` available, cleanup-plan verification can use `clj-kondo --lint .`. Clojure does not currently have a scip-query semantic provider equivalent to TypeScript's `ts-morph` layer; capability output reports that boundary explicitly.
|
|
114
|
+
|
|
102
115
|
## Cleaning Up AI-Generated Code
|
|
103
116
|
|
|
104
117
|
These checks target specific ways AI-assisted development rots a codebase. The full catalog, with prevention wiring for each detector, is in [docs/AI_FAILURE_MODES.md](docs/AI_FAILURE_MODES.md):
|
|
105
118
|
|
|
106
|
-
**1. Find the echoes.** Agents re-implement helpers, hooks, composables, and frontend components they didn't know existed. `recent-duplicates` makes similarity
|
|
119
|
+
**1. Find the echoes.** Agents re-implement helpers, hooks, composables, and frontend components they didn't know existed. `recent-duplicates` makes similarity _directional_ using git file ages - which side is the established original, which is the recent echo.
|
|
120
|
+
|
|
121
|
+
Illustrative output:
|
|
107
122
|
|
|
108
123
|
```
|
|
109
124
|
91% ECHO react-component src/components/ProjectCardVisual.tsx ProjectCardVisual (added 62 commits ago)
|
|
@@ -114,7 +129,9 @@ These checks target specific ways AI-assisted development rots a codebase. The f
|
|
|
114
129
|
(both new - one agent session duplicated itself; consolidate before they diverge)
|
|
115
130
|
```
|
|
116
131
|
|
|
117
|
-
**2. Finish the half-done extraction.** Agents extract a helper, rewire one or two call sites, and abandon the rest — the extracted logic survives inline at every site they missed. `incomplete-migration` finds helpers that are new in the diff, confirms they were wired in somewhere, and lists the established sites that still contain the helper's logic but never call it (containment scoring, because a missed site holds the helper's logic
|
|
132
|
+
**2. Finish the half-done extraction.** Agents extract a helper, rewire one or two call sites, and abandon the rest — the extracted logic survives inline at every site they missed. `incomplete-migration` finds helpers that are new in the diff, confirms they were wired in somewhere, and lists the established sites that still contain the helper's logic but never call it (containment scoring, because a missed site holds the helper's logic _plus_ its own).
|
|
133
|
+
|
|
134
|
+
Illustrative output:
|
|
118
135
|
|
|
119
136
|
```
|
|
120
137
|
src/utils/priceLabel.ts priceLabel()
|
|
@@ -123,7 +140,7 @@ src/utils/priceLabel.ts priceLabel()
|
|
|
123
140
|
un-migrated: 100% buildReportC() (src/cards/price-summary-c.ts)
|
|
124
141
|
```
|
|
125
142
|
|
|
126
|
-
**3. Catch your standards docs lying.** If you keep in-repo standards for agents to read before implementing, a stale standard is worse than none. `doc-drift` reads every doc's file citations
|
|
143
|
+
**3. Catch your standards docs lying.** If you keep in-repo standards for agents to read before implementing, a stale standard is worse than none. `doc-drift` reads every doc's file citations _and_ its co-change history, then flags docs whose code moved on without them — including **broken references** to files that no longer exist:
|
|
127
144
|
|
|
128
145
|
```
|
|
129
146
|
staleness 94 product/domain-model.md
|
|
@@ -131,7 +148,7 @@ staleness 94 product/domain-model.md
|
|
|
131
148
|
22 change(s) since doc update src/workflows/serviceTasks.ts (referenced by doc)
|
|
132
149
|
```
|
|
133
150
|
|
|
134
|
-
**4. Delete with project checks.** `cleanup-plan` runs dead-code analysis to a
|
|
151
|
+
**4. Delete with project checks.** `cleanup-plan` runs dead-code analysis to a _fixpoint_ — deleting batch 0 makes batch 1 dead, and the plan shows the cascade. `--verify` applies each batch in a throwaway git worktree and runs the supported checker detected for your project (differentially, so pre-existing errors don't drown the signal):
|
|
135
152
|
|
|
136
153
|
```
|
|
137
154
|
── Batch 0: deletable now (graph-fact, 67 LOC) ──
|
|
@@ -139,22 +156,44 @@ staleness 94 product/domain-model.md
|
|
|
139
156
|
Batch 0: COMPILER-VERIFIED
|
|
140
157
|
```
|
|
141
158
|
|
|
142
|
-
When verification
|
|
159
|
+
When verification _fails_, the errors name the exact references the static evidence missed — that failure has caught real detector mistakes and stopped build-breaking deletions.
|
|
143
160
|
|
|
144
161
|
**5. Trim speculative generality.** `unused-params` finds trailing parameters no body ever uses (the classic "options for later"), scoped to removals that are type-safe by construction.
|
|
145
162
|
|
|
146
163
|
**6. Keep frontend reuse honest.** React and Vue have dedicated frontend hygiene checks: component-duplicate commands compare JSX/template structure, hook/composable commands compare state/effect/request behavior, and large-component/view commands flag files that concentrate too many reasons to change. `health` includes these as hygiene pressure, while `incomplete-migration` remains the direct check for a hook/composable/helper extraction that was wired into some sites but not all of them.
|
|
147
164
|
|
|
148
|
-
**7. Surface hidden coupling.** `co-change` finds file pairs that repeatedly change in the same commits with
|
|
165
|
+
**7. Surface hidden coupling.** `co-change` finds file pairs that repeatedly change in the same commits with _no_ dependency edge — schema ↔ generated inventory ↔ doc triangles, backend schemas ↔ frontend stores, `.env.example` ↔ its parser. The reference graph cannot see these; the change graph can.
|
|
149
166
|
|
|
150
|
-
**8. Gate every diff.** `diff-gate` runs a defined set of checks scoped to what a change
|
|
167
|
+
**8. Gate every diff.** `diff-gate` runs a defined set of checks scoped to what a change _introduces_ and exits nonzero with remediation text for each finding. Baseline regressions are included when you pass `--baseline`.
|
|
168
|
+
|
|
169
|
+
<!-- BEGIN GENERATED DIFF-GATE CHECKS -->
|
|
170
|
+
| Check | What it catches | When it runs |
|
|
171
|
+
| --- | --- | --- |
|
|
172
|
+
| `echo` | Changed symbols that newly echo established code elsewhere. | Default diff gate. |
|
|
173
|
+
| `incomplete-migration` | New helpers or abstractions wired into some sites while older inline sites remain. | Default diff gate. |
|
|
174
|
+
| `co-change-partner` | Historically coupled files that usually change together but are missing from this diff. | Default diff gate. |
|
|
175
|
+
| `twin-partner` | A changed symbol has a same-(near-)name twin (identical or already-divergent) elsewhere that this diff left untouched. | Default diff gate. Advisory: findings print but never cause a nonzero exit by themselves. |
|
|
176
|
+
| `coverage-contract` | A configured `coverageContracts` entry (.scipquery.json) drifted: its declared key set no longer matches its ground-truth source. | Default diff gate, only when either side of a configured contract changed. |
|
|
177
|
+
| `doc-reference` | Docs that cite changed files and may need a matching update. Dated snapshot docs (docs.snapshotPaths) are excluded by policy. | Default diff gate. Advisory (21.2) for bare file-mention citations; blocking when the citation has a line anchor or the cited file was deleted/renamed. |
|
|
178
|
+
| `unused-params` | Fresh trailing parameters or options that no changed body uses. | Default diff gate. |
|
|
179
|
+
| `new-dead` | Changed production symbols with zero indexed consumers. | Default diff gate. |
|
|
180
|
+
| `baseline` | New health finding identities compared with the committed health baseline. | Only with `diff-gate --baseline`. |
|
|
181
|
+
<!-- END GENERATED DIFF-GATE CHECKS -->
|
|
182
|
+
|
|
183
|
+
Illustrative output:
|
|
151
184
|
|
|
152
185
|
```
|
|
153
186
|
[co-change-partner] schema.prisma changed, but scripts/scope-inventory.mjs did not — they change together 12x (86% of the time)
|
|
154
187
|
-> Update scripts/scope-inventory.mjs alongside this change, or confirm the coupling no longer holds.
|
|
155
188
|
```
|
|
156
189
|
|
|
157
|
-
**9. Ratchet it in CI.** `health --write-baseline` snapshots finding identities into a committable file; `health --baseline` exits 1 on any
|
|
190
|
+
**9. Ratchet it in CI.** `health --write-baseline` snapshots finding identities into a committable file; `health --baseline` exits 1 on any _new_ finding. "Don't get worse" is an objective gate that no score arithmetic can game.
|
|
191
|
+
|
|
192
|
+
**10. Catch byte-identical tiny helpers `similar`'s fingerprints miss.** `duplicate-bodies` normalizes and hashes small callable bodies (comments/whitespace stripped, default `--min-loc 3`) and reports exact matches spanning multiple files — the "escapeRegex copy-pasted into seven files" shape that shape-based similarity scoring is too coarse to flag.
|
|
193
|
+
|
|
194
|
+
**11. Catch a same-name function that drifted apart.** `twin-drift` finds functions with the same (or near-same) name in different files whose bodies have diverged — a strong signal one side got a bug fix, edge case, or feature the other never received. Synthetic leaves and test-only groups are excluded by default.
|
|
195
|
+
|
|
196
|
+
Baseline finding identities are keyed as `detector:file:shortName`. A rename can therefore appear as one fixed identity plus one new identity; refresh the baseline after intentional renames once the changed code has been reviewed.
|
|
158
197
|
|
|
159
198
|
Accepted findings can be recorded without weakening the rest of the gate:
|
|
160
199
|
|
|
@@ -162,13 +201,15 @@ Accepted findings can be recorded without weakening the rest of the gate:
|
|
|
162
201
|
scip-query suppress SQABC123DEF456 --check echo --reason "intentional compatibility shim"
|
|
163
202
|
```
|
|
164
203
|
|
|
165
|
-
This appends a reasoned entry to `.scipquery.json`; `config-validate`
|
|
204
|
+
This appends a reasoned entry to `.scipquery.json`; `config-validate` requires every suppression to include a reason plus either a stable finding id or both `check` and `file`. Check+file suppressions are allowed but warn because they waive every matching finding in that file. `diff-gate --json` reports both active and suppressed findings.
|
|
166
205
|
|
|
167
206
|
Before any edit, `plan-context <target>` bundles the structural picture — definitions, references, call graph, blast radius — plus a HISTORY section: churn, fix-commit density, and the files that usually change together with the target ("editing this usually means editing these").
|
|
168
207
|
|
|
169
208
|
## A Health Score You Can Argue With
|
|
170
209
|
|
|
171
|
-
`scip-query health` refuses to be a vanity number
|
|
210
|
+
`scip-query health` refuses to be a vanity number.
|
|
211
|
+
|
|
212
|
+
Illustrative output:
|
|
172
213
|
|
|
173
214
|
```
|
|
174
215
|
Codebase Health Score: 95/100
|
|
@@ -187,7 +228,7 @@ Axes:
|
|
|
187
228
|
|
|
188
229
|
- **Risk vs. Hygiene** are separate claims: risk components are tied to graph facts and repository-history signals; hygiene components are tidiness. Blending them is how scores become meaningless.
|
|
189
230
|
- **Every deduction is itemized** — the scalar is auditable, not vibes.
|
|
190
|
-
- **The validation axis is a falsifiability loop**: it measures whether flagged files actually attract more fix commits than the rest
|
|
231
|
+
- **The validation axis is a falsifiability loop**: it measures whether flagged files actually attract more fix commits than the rest _in your repo_, per detector. On some codebases a detector tracks repeated fixes; on others it is mostly noise — the tool reports which, instead of assuming.
|
|
191
232
|
- **Suppressions are data**: every `// scip-query: ignore-*` comment is a precision label, counted and reported.
|
|
192
233
|
|
|
193
234
|
## Accuracy Model
|
|
@@ -196,10 +237,12 @@ Evidence tiers are kept explicit, strongest first:
|
|
|
196
237
|
|
|
197
238
|
1. **Compiler-backed facts** from the SCIP database (`trace`, `refs`, `deps`, `outline`, ...).
|
|
198
239
|
2. **Semantic augmentation** via `ts-morph` for TypeScript — verified references, callers, callees when SCIP alone is incomplete.
|
|
199
|
-
3. **Source-backed heuristics** (AST/text) for cleanup signals. Always labeled:
|
|
240
|
+
3. **Source-backed heuristics** (AST/text) for cleanup signals. Always labeled: _"these are candidates, not exact compiler facts."_
|
|
200
241
|
4. **Compiler verification** for deletions — the only tier that earns the word "safe."
|
|
201
242
|
|
|
202
|
-
And because accuracy you don't measure is a feeling, `self-audit` samples symbols and scores the cheap paths against the TypeScript compiler
|
|
243
|
+
And because accuracy you don't measure is a feeling, `self-audit` samples symbols and scores the cheap paths against the TypeScript compiler.
|
|
244
|
+
|
|
245
|
+
Illustrative output:
|
|
203
246
|
|
|
204
247
|
```
|
|
205
248
|
references precision 1.0 recall 0.9 (the cheap path doesn't fabricate; it occasionally misses)
|
|
@@ -209,11 +252,59 @@ Heuristic detectors carry guardrails learned from real codebases: published `pac
|
|
|
209
252
|
|
|
210
253
|
## Agent Skills
|
|
211
254
|
|
|
212
|
-
`scip-query install-skills` symlinks bundled skills into Claude Code, Codex, and shared agent roots (`~/.agents/skills/`) so they update automatically with the package. The `scip-query` router skill dispatches codebase work to
|
|
255
|
+
`scip-query install-skills` symlinks bundled skills into Claude Code, Codex, and shared agent roots (`~/.agents/skills/`) so they update automatically with the package. The `scip-query` router skill dispatches codebase work to the specialist below; when unsure which owns a task, start there.
|
|
256
|
+
|
|
257
|
+
### Bundled skills
|
|
258
|
+
|
|
259
|
+
One-line "essential difference" per skill — read this table before the Routes table in `skills/scip-query/SKILL.md` if two names sound alike.
|
|
260
|
+
|
|
261
|
+
| Skill | Essential difference |
|
|
262
|
+
| --- | --- |
|
|
263
|
+
| `scip-query` | Router: dispatches codebase work to the specialist skill below. |
|
|
264
|
+
| `scip-explore` | Understand before touching. |
|
|
265
|
+
| `scip-concrete-plan` | Specify ONE change so an executor can't guess. |
|
|
266
|
+
| `scip-conductor` | Run a multi-phase program (delegate, verify handoffs, pre-registered benchmarks). |
|
|
267
|
+
| `scip-debug` | Root-cause a failure. |
|
|
268
|
+
| `scip-triage-issue` | Package a report into an actionable issue+fix plan. |
|
|
269
|
+
| `scip-verify` | Post-change closeout gate. |
|
|
270
|
+
| `scip-cleanup-audit` | Rank findings, no edits. |
|
|
271
|
+
| `scip-cleanup-improve` | Autonomously fix confirmed findings. |
|
|
272
|
+
| `scip-maintainability` | Is this well-organized (scattered concepts, accidental variation)? |
|
|
273
|
+
| `scip-integrity-audit` | Is this real (decorative checkers, faked implementations, dead fallback-hidden paths)? |
|
|
274
|
+
| `scip-twin-drift` | Same-name implementations that drifted apart. |
|
|
275
|
+
| `scip-claim-audit` | Status words derived vs asserted. |
|
|
276
|
+
| `scip-probe-reachability` | Prove parser/AST branches actually fire. |
|
|
277
|
+
| `scip-api-impact` | Blast radius before changing public surfaces. |
|
|
278
|
+
| `scip-directory-architecture` | Folder/ownership layout. |
|
|
279
|
+
| `scip-doc-reconcile` | Docs vs code drift. |
|
|
280
|
+
| `scip-diagram` | Visual artifacts. |
|
|
281
|
+
| `scip-react-maintainability` | Framework-specific reuse lens (React). |
|
|
282
|
+
| `scip-vue-maintainability` | Framework-specific reuse lens (Vue). |
|
|
283
|
+
| `scip-language-playbook` | Which commands per language. |
|
|
284
|
+
| `scip-hyper-optimization` | Performance campaigns without output changes. |
|
|
285
|
+
| `scip-tla-model-system` | Formal models tied to code evidence. |
|
|
286
|
+
| `scip-setup` | Adopt or repair scip-query in a repo. |
|
|
287
|
+
| `_shared` | Reference loaded by other skills, not user-invoked. |
|
|
288
|
+
|
|
289
|
+
The confusable clusters, disambiguated: `scip-concrete-plan` (one change) vs `scip-conductor` (a program of changes with delegation); `scip-cleanup-audit` (report only) vs `scip-cleanup-improve` (autonomous fixing loop); `scip-verify` (did this specific change land safely) vs `scip-integrity-audit` (does this code actually work at all) vs `scip-maintainability` (is this well organized) vs `scip-twin-drift` (one drifted same-name pair specifically); `scip-directory-architecture` (folder ownership) vs `scip-maintainability` (deeper structural compression). `skills/scip-query/SKILL.md`'s Tie-Breaks section has the full routing logic.
|
|
290
|
+
|
|
291
|
+
Project setup writes reviewable project-local lifecycle hooks for Codex and Claude Code (`.codex/hooks.json` and `.claude/settings.local.json` by default; `setup-hooks --shared` opts into `.claude/settings.json`). These hooks add scip-query context at session start, route prompts toward the right skill, and run an advisory Stop-hook wrapper around the diff gate only for that repository. The Stop hook sends feedback to the agent by default instead of blocking; set `SCIP_QUERY_STOP_HOOK_MODE=warn` for a warning-only hook response, or `SCIP_QUERY_STOP_HOOK_MODE=block` to enforce the gate. Set `SCIP_QUERY_SKIP_HOOK_INSTALL=1` or run `scip-query setup --no-hooks` to skip hook installation during setup, and run `scip-query setup-hooks --json` later to repair the current repo's hooks.
|
|
292
|
+
|
|
293
|
+
For a project, run `scip-query setup`. It installs/refreshes skills, configures project-local hooks unless skipped, checks indexer readiness, attempts configured indexer remediation, refreshes the index, smoke-tests representative command families, writes `docs/scip-query/health-dossier.md` and `.json`, reports the health score and items needing attention, and seeds AGENTS.md/CLAUDE.md guidance. After setup, `scip-cleanup-audit` confirms raw signals and `scip-cleanup-improve` keeps fixing the worst confirmed items until no safe confirmed cleanup remains. Use `scip-query setup --git-hook` when you also want a local pre-commit diff gate. CI setup is intentionally separate.
|
|
294
|
+
|
|
295
|
+
## Formal Models (TLA+)
|
|
296
|
+
|
|
297
|
+
For the parts of a system where the risk lives in interleaving — retries, concurrency, partial failure, money, a state machine with guards — `scip-query` scaffolds a TLA+ model tied to indexed code and keeps it honest against that code:
|
|
213
298
|
|
|
214
|
-
|
|
299
|
+
```bash
|
|
300
|
+
scip-query tla scaffold src/queue/store.ts # draft spec + config + mapping from indexed code
|
|
301
|
+
scip-query tla verify specs/queue/Queue.tla # mechanical conformance: referents, reads/writes, calls, model checker
|
|
302
|
+
scip-query tla instrument specs/queue/Queue.tla # generate a trace recorder + wiring sites for each mapped action
|
|
303
|
+
scip-query tla trace-check specs/queue/Queue.tla --trace traces/run1.json # check a recorded execution against Next
|
|
304
|
+
scip-query tla fetch-tools # download the pinned tla2tools.jar into the cache
|
|
305
|
+
```
|
|
215
306
|
|
|
216
|
-
|
|
307
|
+
`tla verify` checks the mapping contract against the model text and the indexed code: variable and action referents must resolve to value-like symbols (not types), declared reads/writes are checked against a static scan, and every waiver requires a reason and is counted in the output. At scale, findings are grouped by `(category, modelElement)` with up to 3 exemplars per group by default — pass `--full` to print every finding ungrouped. The `scip-tla-model-system` skill (`scip-query install-skills`) walks the scaffold → verify → instrument → trace-check loop end to end.
|
|
217
308
|
|
|
218
309
|
## Quick Start
|
|
219
310
|
|
|
@@ -224,7 +315,7 @@ scip-query stats
|
|
|
224
315
|
scip-query system src/auth
|
|
225
316
|
scip-query plan-context login
|
|
226
317
|
scip-query diff-impact --json
|
|
227
|
-
scip-query health --json
|
|
318
|
+
scip-query health --json
|
|
228
319
|
scip-query cleanup-plan --verify
|
|
229
320
|
scip-query health --write-baseline # start the ratchet
|
|
230
321
|
```
|
|
@@ -235,18 +326,21 @@ scip-query health --write-baseline # start the ratchet
|
|
|
235
326
|
- `scip` CLI, from [Sourcegraph SCIP releases](https://github.com/sourcegraph/scip/releases)
|
|
236
327
|
- A language-specific SCIP indexer for your project
|
|
237
328
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
|
241
|
-
|
|
|
242
|
-
|
|
|
243
|
-
|
|
|
244
|
-
|
|
|
245
|
-
|
|
|
246
|
-
|
|
|
247
|
-
|
|
|
248
|
-
|
|
|
249
|
-
|
|
|
329
|
+
On Windows, the `scip` binary is installed automatically from npm: `scip-query-scip-windows` is an os-gated optional dependency (universal package, x64 + arm64) that only Windows installs fetch. Resolution order: `scip` on PATH, then `SCIP_QUERY_SCIP_BIN`, then the sidecar package. Run `scip-query check-deps` for platform-specific install instructions.
|
|
330
|
+
|
|
331
|
+
| Language | Indexer | Install |
|
|
332
|
+
| ----------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
333
|
+
| TypeScript / JavaScript / Vue | scip-typescript | `npm install -g @sourcegraph/scip-typescript` |
|
|
334
|
+
| Java / Scala / Kotlin | scip-java | [releases](https://github.com/sourcegraph/scip-java/releases) |
|
|
335
|
+
| Rust | rust-analyzer | Ships with rust-analyzer: `rust-analyzer scip` |
|
|
336
|
+
| Python | scip-python-plus | `npm install -g scip-python-plus` |
|
|
337
|
+
| Go | scip-go | `go install github.com/sourcegraph/scip-go@latest` |
|
|
338
|
+
| Ruby | scip-ruby | [releases](https://github.com/sourcegraph/scip-ruby/releases) |
|
|
339
|
+
| C / C++ | scip-clang | [releases](https://github.com/sourcegraph/scip-clang/releases) |
|
|
340
|
+
| C# / VB | scip-dotnet | [releases](https://github.com/sourcegraph/scip-dotnet/releases) |
|
|
341
|
+
| Dart | scip-dart | [releases](https://github.com/Workiva/scip-dart/releases) or `dart pub global activate scip_dart` |
|
|
342
|
+
| PHP | scip-php | [releases](https://github.com/davidrjenni/scip-php/releases) or Composer package `davidrjenni/scip-php` |
|
|
343
|
+
| Clojure / ClojureScript | scip-clojure | Requires a `scip-clojure` binary on PATH; source: [PlunderStruck/scip-clojure](https://github.com/PlunderStruck/scip-clojure) |
|
|
250
344
|
|
|
251
345
|
For Python, the executable may be `scip-python`, `scip-python-plus`, or both. `scip-query` accepts either name.
|
|
252
346
|
|
|
@@ -265,6 +359,19 @@ By default, indexes live in `~/.cache/scip-query/projects/<hash>/`, keeping proj
|
|
|
265
359
|
TypeScript monorepos can opt into project sharding with `indexer.typescript.projectMode: "workspace"`. In that mode, `scip-query` discovers repo-local TypeScript project roots, runs one `scip-typescript` process per project with bounded concurrency, merges the shard protobufs, and still publishes one TypeScript language index. Set `indexer.typescript.projects` to an explicit list of project directories or tsconfig paths when automatic discovery is too broad. Set `indexerConcurrency` when a repo needs a persistent worker cap; CLI `--indexer-concurrency` and `SCIP_QUERY_INDEXER_CONCURRENCY` still override ad hoc runs.
|
|
266
360
|
Use `indexer.typescript.pnpmWorkspaces` only with the default single-project mode; workspace mode passes explicit projects instead.
|
|
267
361
|
|
|
362
|
+
Clojure projects can pass a project-local `scip-clojure` config file through `.scipquery.json`:
|
|
363
|
+
|
|
364
|
+
```json
|
|
365
|
+
{
|
|
366
|
+
"languages": ["clojure"],
|
|
367
|
+
"indexer": {
|
|
368
|
+
"clojure": {
|
|
369
|
+
"configPath": ".scip-clojure.json"
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
268
375
|
Most read-only commands accept `--json` and use the same envelope:
|
|
269
376
|
|
|
270
377
|
```json
|
|
@@ -279,26 +386,26 @@ Run this in a project root:
|
|
|
279
386
|
scip-query init
|
|
280
387
|
```
|
|
281
388
|
|
|
282
|
-
It creates `.scipquery.json`:
|
|
389
|
+
It creates a minimal `.scipquery.json`:
|
|
283
390
|
|
|
284
391
|
```json
|
|
285
392
|
{
|
|
286
393
|
"languages": ["typescript"],
|
|
287
|
-
"indexerConcurrency": 6,
|
|
288
394
|
"watch": {
|
|
289
395
|
"enabled": false,
|
|
290
396
|
"debounceMs": 30000,
|
|
291
|
-
"cooldownMs": 60000
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
"typescript": {
|
|
295
|
-
"projectMode": "workspace",
|
|
296
|
-
"projects": ["apps/api", "apps/web"]
|
|
297
|
-
}
|
|
397
|
+
"cooldownMs": 60000,
|
|
398
|
+
"gitPollMs": 2000,
|
|
399
|
+
"autoRefresh": true
|
|
298
400
|
}
|
|
299
401
|
}
|
|
300
402
|
```
|
|
301
403
|
|
|
404
|
+
Add optional fields such as `indexerConcurrency`, `indexer`, `entryRoots`,
|
|
405
|
+
`declaredCouplings`, and `suppressions` only when the project needs them.
|
|
406
|
+
|
|
407
|
+
`scip-query watch` is a foreground process. It writes a project-local watcher lock and refuses a second watcher for the same index cache; keep one terminal running it, or stop it with Ctrl+C before starting another.
|
|
408
|
+
|
|
302
409
|
Use `declaredCouplings` for files that intentionally form one maintenance unit.
|
|
303
410
|
These pairs are treated as structurally linked by `co-change` and health, while
|
|
304
411
|
still appearing in file-specific exploration. The cleanup detector example
|
|
@@ -321,14 +428,20 @@ because they share candidate and evidence policy changes:
|
|
|
321
428
|
}
|
|
322
429
|
```
|
|
323
430
|
|
|
431
|
+
The consumer evidence product migration kept this declared-coupling example
|
|
432
|
+
current: `src/queries/cleanup/stale-abstractions.ts` still belongs to the
|
|
433
|
+
cleanup detector family and still shares candidate/evidence policy with the
|
|
434
|
+
dead and isolated cleanup detectors.
|
|
435
|
+
|
|
324
436
|
Useful environment variables:
|
|
325
437
|
|
|
326
|
-
| Variable
|
|
327
|
-
|
|
328
|
-
| `SCIP_QUERY_PROJECT_ROOT` | Override the project root directory
|
|
329
|
-
| `SCIP_QUERY_INDEX_DB`
|
|
330
|
-
| `SCIP_QUERY_INDEX_SCIP`
|
|
331
|
-
| `SCIP_QUERY_CACHE_DIR`
|
|
438
|
+
| Variable | Purpose |
|
|
439
|
+
| ------------------------- | --------------------------------------------------------------------- |
|
|
440
|
+
| `SCIP_QUERY_PROJECT_ROOT` | Override the project root directory |
|
|
441
|
+
| `SCIP_QUERY_INDEX_DB` | Override the SQLite database path |
|
|
442
|
+
| `SCIP_QUERY_INDEX_SCIP` | Override the SCIP protobuf path |
|
|
443
|
+
| `SCIP_QUERY_CACHE_DIR` | Override the cache directory |
|
|
444
|
+
| `SCIP_QUERY_SCIP_BIN` | Path to a local `scip` binary (overrides PATH and the Windows sidecar) |
|
|
332
445
|
|
|
333
446
|
Query results are filtered through the project's `.gitignore`. If none exists, common generated directories such as `dist/`, `target/`, `node_modules/`, and `.venv/` are excluded by default.
|
|
334
447
|
|
|
@@ -339,7 +452,7 @@ Query results are filtered through the project's `.gitignore`. If none exists, c
|
|
|
339
452
|
- [Agent Guide](docs/AGENT_GUIDE.md): goal-oriented workflows for tracing, planning, cleanup, quality checks, and change verification.
|
|
340
453
|
- [Command Reference](docs/COMMAND_REFERENCE.md): generated command syntax, descriptions, and options.
|
|
341
454
|
- [Programmatic API](docs/API.md): using the query functions from TypeScript.
|
|
342
|
-
- [Historical plans](docs/plans
|
|
455
|
+
- [Historical plans](https://github.com/PlunderStruck/scip-query/tree/main/docs/plans): implementation notes and completed cleanup plans.
|
|
343
456
|
|
|
344
457
|
## License
|
|
345
458
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{e as t}from"./chunk-FERAXG6Y.js";import{writeFileSync as o}from"fs";import{workerData as s}from"worker_threads";var e=s;try{let r=t({projectRoot:e.projectRoot,dbPath:e.dbPath,tsconfig:e.tsconfig,vueFiles:e.vueFiles,tasks:e.tasks});o(e.resultPath,JSON.stringify({ok:!0,result:r}))}catch(r){o(e.resultPath,JSON.stringify({ok:!1,error:r instanceof Error?r.message:String(r)}))}finally{let r=new Int32Array(e.sharedBuffer);Atomics.add(r,0,1),Atomics.notify(r,0)}
|
|
2
2
|
//# sourceMappingURL=augment-vue-worker.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{b as oe}from"./chunk-B75HZHUP.js";import{a as N}from"./chunk-X4O6K47U.js";import{b as J,e as $,f as G,g as X}from"./chunk-NAH5EAZS.js";import{c as se}from"./chunk-QJ3FK4TB.js";import{c as Y,d as ee,e as te,f as ne,l as ie}from"./chunk-WFGOH2UI.js";import{e as re}from"./chunk-C4ICAIJ4.js";import{j as Q,o as _}from"./chunk-R3JY4EZ4.js";import{d as U,g as H,h as V,i as K,j as Z,k as q}from"./chunk-HXXMPYEF.js";import{m as W}from"./chunk-T2FQ4GHD.js";import{A as P,x as z}from"./chunk-ISLWJ4PY.js";import{b as O,l as b,m as B,o as j,p as I}from"./chunk-WS3Z6W3M.js";import{c as w}from"./chunk-GNG622H3.js";import{a as R}from"./chunk-64MNV6AB.js";import{b as L}from"./chunk-7S5E7KWT.js";var x=new WeakMap,ae=B({kind:"definition-exclusions",invalidation:j("definition-exclusions"),serialize:e=>JSON.stringify(e),deserialize:De});function le(e,t){let n=z(t);if(!(n==="rust"||n==="typescript"||n==="tsx"||n==="javascript"))return[];let r=I(e,t);if(!r)return[];let s=O(e,t,r),a=ae.read(e,t,s);if(a)return a;let u=n==="rust"?Te(e,t):Pe(e,t);return ae.write(e,t,s,u),u}function De(e){try{let t=JSON.parse(e);return!Array.isArray(t)||!t.every(Le)?null:t}catch{return null}}function Le(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.startLine!="number"||!Number.isFinite(t.startLine)||typeof t.endLine!="number"||!Number.isFinite(t.endLine)||typeof t.reason!="string"?!1:t.containerName===void 0||typeof t.containerName=="string"}var ue=new Set(["describe","it","test","fdescribe","fit","xdescribe","xit","beforeEach","afterEach","beforeAll","afterAll","before","after","suite","bench","benchmark"]),we=/\b(?:describe|it|test|fdescribe|fit|xdescribe|xit|beforeEach|afterEach|beforeAll|afterAll|before|after|suite|bench|benchmark)\s*\(/,Ie=/\b(?:export\s+)?(?:async\s+)?function\s+use[A-Z][A-Za-z0-9_$]*\b|\b(?:const|let|var)\s+use[A-Z][A-Za-z0-9_$]*\s*(?::[^=;]+)?=\s*(?:async\s*)?(?:function\b|(?:<[^=;{]+>\s*)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>)/;function Pe(e,t){let n=I(e,t);if(!n||!Ne(n))return[];let i=P(e,t);if(!i)return[];let r=x.get(i);if(r)return r;let s=!1,a=i.rootNode;for(let l of a.namedChildren){if(l.type!=="expression_statement")continue;let d=l.namedChild(0);if(!d||d.type!=="call_expression")continue;let o=d.namedChild(0);if(!o)continue;let c=o.type==="member_expression"?o.namedChild(o.namedChildCount-1)?.text:o.text;if(c&&ue.has(c)){s=!0;break}}let u=[];s&&u.push({startLine:0,endLine:a.endPosition.row,reason:"TS/JS test file (describe/it/test at top level)"});for(let l of a.namedChildren){let d=null,o=null;if(l.type==="function_declaration")d=l.namedChild(0)?.text??null,o=l;else if(l.type==="export_statement"){let c=l.namedChild(0);c?.type==="function_declaration"&&(d=c.namedChild(0)?.text??null,o=c)}else if(l.type==="lexical_declaration"){let c=l.namedChild(0);if(c?.type==="variable_declarator"){let p=c.namedChild(0)?.text,m=c.namedChild(1);p&&(m?.type==="arrow_function"||m?.type==="function_expression")&&(d=p,o=c)}}d&&/^use[A-Z]/.test(d)&&o&&u.push({startLine:o.startPosition.row,endLine:o.endPosition.row,reason:"React custom hook (use*)"})}return u.push(...de(i,new Set(["function_declaration","method_definition","class_declaration","interface_declaration","type_alias_declaration","enum_declaration","variable_declarator","export_statement"]),new Set(["comment"]))),x.set(i,u),u}function Ne(e){if(e.includes("scip-query"))return!0;let t=!1;for(let n of ue)if(e.includes(n)){t=!0;break}return t&&we.test(e)?!0:e.includes("use")&&Ie.test(e)}var ke=/scip-query[\s:-]*ignore[\s:-]*(?:dead(?:-code)?|stale)?/i;function Fe(e){return ke.test(e)}function de(e,t,n){let i=[],r=s=>{if(t.has(s.type)&&s.parent){let u=s.parent.children,l=-1;for(let d=0;d<u.length;d+=1)if(u[d].startIndex===s.startIndex&&u[d].type===s.type){l=d;break}if(l>0)for(let d=l-1;d>=0;d-=1){let o=u[d];if(n.has(o.type)){if(Fe(o.text)){i.push({startLine:s.startPosition.row,endLine:s.endPosition.row,reason:"scip-query suppression comment"});break}continue}if(!(o.type==="attribute_item"||o.type==="inner_attribute_item"))break}}for(let a of s.namedChildren)r(a)};return r(e.rootNode),i}function Te(e,t){let n=P(e,t);if(!n)return[];let i=x.get(n);if(i)return i;let r=[],s=Ae(n);return s?(x.set(n,s),s):(fe(n.rootNode,r,!1,!1),r.push(...de(n,new Set(["function_item","function_signature_item","struct_item","enum_item","union_item","impl_item","mod_item","static_item","const_item"]),new Set(["line_comment","block_comment"]))),r.push(...He(n.rootNode)),x.set(n,r),r)}function Ae(e){return Ve(e.rootNode)?[{startLine:0,endLine:e.rootNode.endPosition.row,reason:"generated file (@generated header)"}]:null}function fe(e,t,n,i){let r=n,s=i;e.type==="trait_item"&&t.push({startLine:e.startPosition.row,endLine:e.endPosition.row,reason:"trait declaration body (dynamic dispatch)"}),e.type==="impl_item"&&e.childForFieldName("trait")&&(s=!0,t.push({startLine:e.startPosition.row,endLine:e.endPosition.row,reason:"trait impl block (dynamic dispatch)"})),e.type==="function_item"||e.type==="function_signature_item"?Me(e,t,n,i):i&&Ue(e)?t.push({startLine:e.startPosition.row,endLine:e.endPosition.row,reason:"trait impl associated item (dynamic dispatch)"}):e.type==="struct_item"||e.type==="enum_item"||e.type==="union_item"?Oe(e,t,n):e.type==="mod_item"&&k(e).some(a=>/#\[\s*cfg\s*\(\s*test\s*\)/.test(a))&&(r=!0);for(let a of e.namedChildren)fe(a,t,r,s)}function Me(e,t,n,i){let r=k(e),s=null;i?s="trait impl method (dynamic dispatch)":n&&(s="inside #[cfg(test)] mod");for(let a of r){let u=je(a);if(u){s=u;break}if(me(a)){s="#[allow(dead_code)]";break}}s&&t.push({startLine:e.startPosition.row,endLine:e.endPosition.row,reason:s})}function Oe(e,t,n){let i=k(e),r=e.namedChildren.find(s=>s.type==="type_identifier")?.text;i.some(We)&&t.push({startLine:e.startPosition.row,endLine:e.endPosition.row,reason:"#[derive(<reflective>)] \u2014 fields accessed via macro/reflection",containerName:r}),i.some(me)&&t.push({startLine:e.startPosition.row,endLine:e.endPosition.row,reason:"#[allow(dead_code)]",containerName:r}),n&&t.push({startLine:e.startPosition.row,endLine:e.endPosition.row,reason:"inside #[cfg(test)] mod",containerName:r})}function k(e){let t=e.parent;if(!t)return[];let n=t.children,i=-1;for(let s=0;s<n.length;s+=1)if(n[s].startIndex===e.startIndex&&n[s].type===e.type){i=s;break}if(i<=0)return[];let r=[];for(let s=i-1;s>=0;s-=1){let a=n[s];if(a.type==="attribute_item"||a.type==="inner_attribute_item")r.push(a.text);else{if(a.type==="line_comment"||a.type==="block_comment")continue;break}}return r}var Be=[{re:/#\[\s*tauri::command\b/,reason:"#[tauri::command]"},{re:/#\[\s*command\b/,reason:"#[command]"},{re:/#\[\s*test\b/,reason:"#[test]"},{re:/#\[\s*bench\b/,reason:"#[bench]"},{re:/#\[\s*tokio::test\b/,reason:"#[tokio::test]"},{re:/#\[\s*async_std::test\b/,reason:"#[async_std::test]"},{re:/#\[\s*wasm_bindgen\b/,reason:"#[wasm_bindgen]"},{re:/#\[\s*no_mangle\b/,reason:"#[no_mangle]"},{re:/#\[\s*napi\b/,reason:"#[napi]"},{re:/#\[\s*pyfunction\b/,reason:"#[pyfunction]"},{re:/#\[\s*pymethod\b/,reason:"#[pymethod]"},{re:/#\[\s*pyo3\b/,reason:"#[pyo3]"},{re:/#\[\s*cfg\s*\(\s*test\s*\)/,reason:"#[cfg(test)]"},{re:/#\[\s*doc\s*\(\s*hidden\s*\)/,reason:"#[doc(hidden)]"}];function je(e){return Be.find(({re:t})=>t.test(e))?.reason??null}var ze=[/\bSerialize\b/,/\bDeserialize\b/,/\bFromRow\b/,/\bsqlx::FromRow\b/,/\bDeriveEntityModel\b/,/\bIntoSchema\b/,/\bToSchema\b/,/\bDeriveValueType\b/,/\bError\b/,/\bthiserror::Error\b/];function We(e){return/#\[\s*derive\s*\(/.test(e)?ze.some(t=>t.test(e)):!1}function me(e){return/#\[\s*allow\s*\(\s*dead_code\s*\)/.test(e)}function Ue(e){return e.type==="const_item"||e.type==="type_item"||e.type==="static_item"||e.type==="associated_type"}function He(e){let t=Ze(e);if(t.size===0)return[];let n=[];for(let i of e.descendantsOfType("mod_item")){let r=i.childForFieldName("name")?.text;r&&t.has(r)&&n.push({startLine:i.startPosition.row,endLine:i.endPosition.row,reason:'serde `with = "..."` module \u2014 body invoked via reflection',containerName:r})}return n}function Ve(e){for(let t=0;t<Math.min(e.namedChildCount,12);t+=1){let n=e.namedChild(t);if(!n||n.type!=="line_comment"&&n.type!=="block_comment")break;if(/@generated\b/.test(n.text)||/This file is .*generated\b/i.test(n.text)||/Code generated by/i.test(n.text)||/Generated by:\s*https?:\/\/openapi-generator/i.test(n.text)||/openapi-generator/i.test(n.text)&&/Generated by/i.test(n.text))return!0}return!1}var Ke=/^#!?\[\s*serde\s*\(/,ce=/\bwith\s*=\s*"([^"]+)"/g;function Ze(e){let t=new Set;for(let n of e.descendantsOfType("attribute_item")){if(!Ke.test(n.text))continue;ce.lastIndex=0;let i;for(;(i=ce.exec(n.text))!==null;){let r=i[1],s=r.split("::").pop()??r;s&&t.add(s)}}return t}function pe(e){let t=new Map,n=i=>{let r=t.get(i);if(r)return r;let s=le(e,i);return r={ranges:s.map(a=>({startLine:a.startLine,endLine:a.endLine})),containers:new Set(s.map(a=>a.containerName).filter(a=>!!a))},t.set(i,r),r};return(i,r,s,a)=>{let u=n(i);for(let l of u.ranges)if(r>=l.startLine&&r<=l.endLine)return!0;if(a&&u.containers.has(a))return!0;for(let l of _(s))if(u.containers.has(l))return!0;return!1}}function gt(e,t={}){L(e,{groups:t.semanticProvider===!0?["whole-project","semantic-provider"]:["whole-project"]})}function be(e,t,n={}){L(e,{groups:n.definitions===!0?["source-file","definition-catalog"]:["source-file"],file:t.replace(/\\/g,"/")})}function ye(e,t){return t.isIgnoredPath(e.relativePath)?y("ignored-file"):K(e.symbol)?y("module-like-symbol"):E(e.symbol)?!e.isFunctionLike&&e.enclosingSymbol&&E(e.enclosingSymbol)?y("nested-non-callable-value"):!t.includeTests&&!S(e.relativePath)?y("test-file"):!t.includeTests&&t.isExcludedRegion(e.relativePath,e.startLine,e.symbol,e.parentTypeName)?y("excluded-file-region"):Z(e.symbol)?y("rust-trait-impl-member"):q(e.symbol)?y("rust-test-module"):!t.includeMembers&&!qe(e)?y("member"):e.endLine-e.startLine+1<t.minLoc?y("below-min-loc"):{accepted:!0}:y("non-value-symbol")}function S(e){return J(e)!=="test"}function y(e){return{accepted:!1,rejectionReason:e}}function E(e){return V(e)||e.endsWith("().")||e.endsWith(".")}function qe(e){return H(e.symbol)||_(e.symbol).length===0}function ge(){return new Map}function he(e,t,n){let i=new Map;for(let r of Y(e,n))e.isIgnored(r.relative_path)||t.has(r.relative_path)||v(i,r.symbol_id,r.relative_path,r.ref_count,"scip-mention");return i}function xe(e,t,n,i={}){let r=new Set;if(i.conservative||n.size===0){for(let s of te(e,t))r.add(s.symbol_id);return r}for(let s of ee(e,t))e.isIgnored(s.relative_path)||n.has(s.relative_path)||r.add(s.symbol_id);return r}function F(e,t){let n=e.get(t);if(!n)return!1;for(let i of n.values())if(i.occurrences>0)return!0;return!1}function C(e,t,n){let i=e.get(t);if(!i)return!1;for(let[r,s]of i)if(r!==n&&s.occurrences>0)return!0;return!1}function Se(e){return e?.occurrences??0}function v(e,t,n,i,r="source-fallback"){if(i<=0)return;let s=_e(e,t,n);s.occurrences+=i,s.sources.add(r)}function Re(e,t,n,i,r){if(i<=0)return;let s=_e(e,t,n);s.occurrences=Math.max(i,s.occurrences),s.sources.add(r)}function _e(e,t,n){let i=e.get(t);i||(i=new Map,e.set(t,i));let r=i.get(n);return r||(r={occurrences:0,sources:new Set},i.set(n,r)),r}var Je=3e3,$e=1e3;function Ut(e,t={}){let{scope:n,minLoc:i=1,includeTests:r=!1,skipBarrels:s=!1,includeMembers:a=!1,deadCodeOnly:u=!1,scanLimit:l,semantic:d=!0}=t,o=0,c=b("dead.candidates",()=>{let f=oe(Ge(e,{scope:n,minLoc:i,includeTests:r,includeMembers:a}),l);return o=f.length,f},()=>({definitions:o})),p=0,m=s?b("dead.inactive-barrels",()=>{let f=new Set($(e));return p=f.size,f},()=>({paths:p})):new Set,T=0,g=u?ge():b("dead.mention-reference-counts",()=>{let f=he(e,m,c.map(D=>D.symbolId));return T=f.size,f},()=>({definitions:c.length,symbolsWithReferences:T})),A=0,Ce=u?b("dead.mentioned-symbol-ids",()=>{let f=xe(e,c.map(D=>D.symbolId),m,{conservative:m.size===0});return A=f.size,f},()=>({definitions:c.length,referencedSymbols:A})):new Set,h=u?c.filter(f=>!Ce.has(f.symbolId)):c.filter(f=>!C(g,f.symbolId,f.relativePath));u?b("dead.source-fallback.dead-code-only",()=>tt(e,h,g,{includeTests:r,inactiveBarrelPaths:m}),()=>({definitions:h.length,includeTests:r})):b("dead.source-fallback.ast",()=>et(e,h,g,{includeTests:r,inactiveBarrelPaths:m}),()=>({definitions:h.length,includeTests:r}));let M=u?h.filter(f=>!F(g,f.symbolId)):h.filter(f=>!C(g,f.symbolId,f.relativePath));b("dead.caller-map-supplement",()=>ot(e,M,g,{includeTests:r,inactiveBarrelPaths:m,includeSemantic:!u&&d}),()=>({definitions:M.length,semantic:!u&&d}));let ve=u?h.filter(f=>!F(g,f.symbolId)):c;return Ye(e,Xe(ve,g))}function Ge(e,t){let n=pe(e),i=[];for(let r of Q(e,{scope:t.scope,symbolMatches:E,sqlPrefilter:"function-like"}))ye(r,{minLoc:t.minLoc,includeTests:t.includeTests,includeMembers:t.includeMembers,isIgnoredPath:a=>e.isIgnored(a),isExcludedRegion:n}).accepted&&i.push(r);return i}function Xe(e,t){return e.map(n=>Qe(n,t)).filter(n=>n.cross_file_refs===0).sort((n,i)=>i.loc-n.loc||n.relative_path.localeCompare(i.relative_path)||n.start_line-i.start_line)}function Qe(e,t){let n=t.get(e.symbolId)??new Map,i=Se(n.get(e.relativePath)),r=0;for(let[s,a]of n)s!==e.relativePath&&(r+=a.occurrences);return{relative_path:e.relativePath,start_line:e.startLine,end_line:e.endLine,loc:e.endLine-e.startLine+1,symbol:e.symbol,same_file_refs:i,cross_file_refs:r}}function Ye(e,t){let n=[],i=0,r=0,s=0;for(let a of t){if(e.isIgnored(a.relative_path)||G(e,a.relative_path)||X(e,a.symbol,a.relative_path))continue;let u=a.same_file_refs===0?"dead-code":"file-internal";u==="dead-code"?i++:r++,s+=a.loc,n.push({relativePath:a.relative_path,startLine:a.start_line,endLine:a.end_line,loc:a.loc,symbol:a.symbol,shortName:U(a.symbol),sameFileRefs:a.same_file_refs,kind:u})}return{symbols:n,counts:{total:n.length,deadCode:i,fileInternal:r,loc:s},totalCount:n.length,deadCodeCount:i,fileInternalCount:r,totalLoc:s}}function et(e,t,n,i){if(t.length===0)return;let r=new N(e),s=new Set(t.map(l=>l.symbolId)),a=new Set(t.map(l=>l.leaf).filter(Boolean)),u=new Set(r.sourceFiles());for(let l of R(e))u.add(l);r.scanSourceReferences({paths:u,includeVueSfc:!0,includeCrossLanguageDispatchNames:!0,includeRustAttributeNames:!0,identifierResolution:"permissive",candidateNames:a,skipPath:l=>i.inactiveBarrelPaths.has(l)||!i.includeTests&&!S(l)},l=>{s.has(l.target.symbolId)&&(it(e,l)||v(n,l.target.symbolId,l.sourceFile,st(l),"source-fallback"))})}function tt(e,t,n,i){if(t.length===0)return;let r=new N(e),s=nt(t),a=new Set(r.sourceFiles());for(let o of R(e))a.add(o);let u=new Set(s.keys()),l=new Map,d=o=>{let c=l.get(o);return c||(c=ie(e,o),l.set(o,c)),c};r.scanSourceReferences({paths:a,includeVueSfc:!0,includeCrossLanguageDispatchNames:!0,includeRustAttributeNames:!0,identifierResolution:"permissive",candidateNames:u,skipPath:o=>i.inactiveBarrelPaths.has(o)||!i.includeTests&&!S(o),resolveTargets:({sourceFile:o,name:c,kind:p})=>{let m=s.get(c);return m?rt(o,c,m,()=>d(o),{permissive:p!=="cross-language-dispatch"}):[]},afterPath:o=>{l.delete(o),be(e,o)}},o=>{let c=o.kind==="identifier"&&o.sourceFile===o.target.relativePath?Math.max(0,o.occurrences-1):o.occurrences;o.kind==="identifier"&&Ee(e,{sourceFile:o.sourceFile,name:o.name,target:o.target,occurrences:c})||v(n,o.target.symbolId,o.sourceFile,c,"source-fallback")})}function nt(e){let t=new Map;for(let n of e){if(!n.leaf)continue;let i=t.get(n.leaf)??[];i.push(n),t.set(n.leaf,i)}return t}function rt(e,t,n,i,r){let s=n.filter(d=>d.relativePath===e);if(s.length>0)return s;if(!r.permissive&&n.length===1)return[...n];let a=i(),u=a.get(t);if(u)for(let d of u){let o=n.filter(c=>w(d,c.relativePath));if(o.length>0)return o}let l=new Set;for(let d of a.values())for(let o of d)l.add(o);for(let d of l){let o=n.filter(c=>w(d,c.relativePath));if(o.length>0&&o.length===n.length)return o}return r.permissive?[...n]:[]}function it(e,t){return t.kind==="cross-language-dispatch"&&t.target.relativePath===t.sourceFile?!0:t.kind==="identifier"&&Ee(e,t)}function st(e){return e.kind==="identifier"&&e.target.relativePath===e.sourceFile?Math.max(0,e.occurrences-1):e.occurrences}function Ee(e,t){return t.occurrences>1?!1:W(e,t.sourceFile).some(n=>n.used||n.sourcePath!==t.target.relativePath?!1:n.importedName===t.name||n.localName===t.name)}function ot(e,t,n,i){let r=i.includeSemantic!==!1,s=r&&t.length>=Je&&R(e).length>=$e,a=(o,c)=>{c===o.relativePath||e.isIgnored(c)||i.inactiveBarrelPaths.has(c)||!i.includeTests&&!S(c)||Re(n,o.symbolId,c,1,"caller-map")};if(s?b("dead.caller-map.mention-chunks",()=>at(e,t,a),()=>({definitions:t.length})):b("dead.caller-map.per-symbol",()=>{for(let o of t){let c=se(e,o,{semantic:r});if(c.length!==0)for(let p of c)a(o,p.file)}},()=>({definitions:t.length,semantic:r})),!s)return;let u=0,l=b("dead.caller-map.semantic-candidates",()=>{let o=t.filter(c=>!C(n,c.symbolId,c.relativePath));return u=o.length,o},()=>({definitions:t.length,semanticCandidates:u}));if(l.length===0)return;let d=re(e,l);for(let o of l){let c=d.get(o.symbolId);if(c)for(let p of c)a(o,p)}}function at(e,t,n){let i=new Map(t.map(r=>[r.symbolId,r]));for(let r of ne(e,[...i.keys()])){let s=i.get(r.symbol_id);s&&n(s,r.relative_path)}}export{gt as a,Ut as b};
|
|
2
|
+
//# sourceMappingURL=chunk-343O6EVV.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{a as j}from"./chunk-QARYU7R3.js";import{a as N,b as g,c as W}from"./chunk-VGMUFW3J.js";import{a as _}from"./chunk-K6UI6EBZ.js";import{a as E}from"./chunk-B75HZHUP.js";import{a as P}from"./chunk-X4O6K47U.js";import{a as k}from"./chunk-BGBBVSH4.js";import{g as C}from"./chunk-QJ3FK4TB.js";import{a as w}from"./chunk-WFGOH2UI.js";import{m as L}from"./chunk-R3JY4EZ4.js";import{d,e as y,k as v}from"./chunk-HXXMPYEF.js";import{g as x}from"./chunk-T2FQ4GHD.js";import{l as S}from"./chunk-WS3Z6W3M.js";import{basename as m,extname as b}from"path";function ae(t,n){let{scope:e,maxLoc:i=15,limit:a=30,scanLimit:o}=n??{},r=new P(t),s=z(r.fileDependencyGraph(e));return _({candidates:()=>B(t,r,e,i),orderCandidates:E,scanLimit:o,profile:{name:"wrapper-candidates"},prepare:l=>({callerFileMap:A(t,r,l,{semantic:n?.semantic!==!1}),reverseFanIn:s}),evaluate:(l,u)=>O(t,r,l,u),orderResults:(l,u)=>u.callerFanIn-l.callerFanIn||u.loc-l.loc,limit:a})}function A(t,n,e,i){let a=N(t,n),o=g(a.forDefinitions(e,{semantic:!1,sourceFallback:!1})),r=[];i.semantic&&S("wrapper.semantic-candidates",()=>{r=e.filter(c=>F(t,n,c,o).length<=1)},()=>({symbols:e.length,semanticCandidates:r.length}));let s=r.length===0?new Map:g(a.forDefinitions(r,{semantic:!0,sourceFallback:!1})),l=s.size===0?o:C(o,s),u=new Map(e.map(c=>[c.symbolId,c])),f=new Map;for(let c of e){let I=F(t,n,c,l);if(I.length>1||(f.set(c.symbolId,c),I.length!==1))continue;let D=I[0],M=R(t,c.symbolId,D);if(!M)continue;let p=T(n,t,D,c.symbol,M);p?.isFunctionLike&&u.has(p.symbolId)&&f.set(p.symbolId,u.get(p.symbolId))}let h=[...f.values()];return h.length===0?l:C(l,g(a.forDefinitions(h,{semantic:!1,sourceFallback:!0})))}function O(t,n,e,i){let a=F(t,n,e,i.callerFileMap);if(a.length!==1)return null;let o=a[0],r=R(t,e.symbolId,o);if(!r)return null;let s=T(n,t,o,e.symbol,r);if(s&&v(s.symbol))return null;let{fanIn:l,source:u}=J(i.callerFileMap,i.reverseFanIn,o,s);if(u==="function"?l<=3:l<=5)return null;let f=H(t,e,o,s);return{symbol:e.symbol,shortName:d(e.symbol),file:e.relativePath,startLine:e.startLine,endLine:e.endLine,loc:k(e),singleCaller:s?.symbol??"",singleCallerShort:s?.isFunctionLike?d(s.symbol):m(o),callerFanIn:l,actionTier:f.length>0?"signal":"direct",boundaryEvidence:f}}function B(t,n,e,i){return n.productionCallableDefinitions({scope:e,minLoc:2,maxLoc:i,requireFunctionLikeSymbol:!0,excludeRootedSymbols:!0}).filter(a=>!x(t,a))}function F(t,n,e,i){let a=m(e.relativePath,b(e.relativePath)),o=[...i.get(e.symbolId)??[]].filter(r=>r!==e.relativePath).filter(r=>m(r,b(r))!==a).filter(r=>{let s=n.fileKind(r);return s!=="barrel"&&s!=="entry"&&s!=="test"});return W(t,e,o).realConsumers}function R(t,n,e){return t.get(`SELECT c.start_line, c.end_line
|
|
2
|
+
FROM mentions m
|
|
3
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
4
|
+
JOIN documents d ON c.document_id = d.id
|
|
5
|
+
WHERE m.symbol_id = ? AND m.role != 1 AND d.relative_path = ?
|
|
6
|
+
LIMIT 1`,n,e)}function T(t,n,e,i,a){let o=t.definitionsForFile(e),r=q(n,e,i,a.start_line,a.end_line);return L(o,r)}function J(t,n,e,i){if(i?.isFunctionLike){let a=[...t.get(i.symbolId)??[]].filter(o=>o!==i.relativePath);if(a.length>0)return{fanIn:a.length,source:"function"}}return{fanIn:G(n,e),source:"file"}}function q(t,n,e,i,a){let o=y(e);if(!o)return i;let r=w(t,n).get(o);if(!r||r.length===0)return i;for(let s of r)if(s>=i&&s<=a)return s;return i}function z(t){let n=new Map;for(let[e,i]of t){n.has(e)||n.set(e,n.get(e)??0);for(let a of i)n.set(a,(n.get(a)??0)+1)}return n}function G(t,n){let e=t.get(n)??0;if(e>0)return e;let i=m(n,b(n)),a=0;for(let[o,r]of t)o!==n&&m(o,b(o))===i&&r>a&&(a=r);return a}function H(t,n,e,i){return j(t,n.relativePath,n.startLine,"wrapper","explicit ignore-wrapper comment",[{label:"wrapper name",value:d(n.symbol)},{label:"caller name",value:i?.symbol?d(i.symbol):m(e)},{label:"wrapper path",value:n.relativePath},{label:"caller path",value:e}])}export{ae as a};
|
|
7
|
+
//# sourceMappingURL=chunk-3KDUITBE.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{c as i}from"./chunk-B75HZHUP.js";import{a,c as m}from"./chunk-QJ3FK4TB.js";import{a as r}from"./chunk-WQHWIVA7.js";import{d as o}from"./chunk-HXXMPYEF.js";function S(s,n,c={}){let e=r(s,n);if(!e)return null;let t=c.semantic!==!1,y=m(s,e,{limit:50,semantic:t}),b=i(a(s,e,{limit:50,additive:!0,callableOnly:!0,semantic:t}));return{symbol:e.symbol,shortName:o(e.symbol),callers:y.map(l=>({symbol:l.symbol,shortName:o(l.symbol),file:l.file})),callees:b.map(l=>({symbol:l.symbol,shortName:o(l.symbol),file:l.file}))}}export{S as a};
|
|
2
|
+
//# sourceMappingURL=chunk-3T2FNHIU.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as f}from"./chunk-X4O6K47U.js";import{a as L}from"./chunk-WQHWIVA7.js";import{d as i,e as b,f as u,l as c}from"./chunk-HXXMPYEF.js";import{d as l}from"./chunk-T2FQ4GHD.js";import{x as a}from"./chunk-ISLWJ4PY.js";function S(o,s){let t=L(o,s);if(!t)return[];let e=new f(o).definitionsForFile(t.relativePath).filter(r=>r.symbol!==t.symbol).filter(r=>c(t.symbol,r.symbol)).sort((r,m)=>r.startLine-m.startLine||r.endLine-m.endLine).map(r=>({symbol:r.symbol,shortName:i(r.symbol),startLine:r.startLine,endLine:r.endLine,kind:u(r.symbol)??"unknown"}));return a(t.relativePath)!=="clojure"?e:d(e,y(o,t))}function y(o,s){let t=b(s.symbol);if(!t)return[];let n=i(s.symbol);return(l(o,s.relativePath)?.clojureMembers??[]).filter(e=>e.ownerName===t).map(e=>({symbol:`${s.symbol}${e.memberName}().`,shortName:`${n}:${e.memberName}()`,startLine:e.startLine,endLine:e.endLine,kind:e.memberKind}))}function d(o,s){let t=new Map;for(let n of[...o,...s])t.set(`${n.shortName}:${n.startLine}:${n.endLine}`,n);return[...t.values()].sort((n,e)=>n.startLine-e.startLine||n.endLine-e.endLine)}export{S as a};
|
|
2
|
+
//# sourceMappingURL=chunk-3V6JQQM5.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as R,b as P}from"./chunk-KJCDEDQW.js";import{a as C,c as B,e as a,f}from"./chunk-6XA4LDHY.js";import{a as v,b as h,c as k}from"./chunk-KMVGRIO2.js";import{F as g}from"./chunk-ISLWJ4PY.js";function D(e,o={}){let{minSimilarity:r=.62,minTokens:n=8,limit:l=20,scope:m,scanLimit:d,filePattern:p,focusFiles:u}=o,c=g(e).reactProfiles({scope:m,minJsxTokens:n,scanLimit:d}).filter(t=>t.kind==="component").map(t=>({file:t.file,component:t.name,tokens:t.jsxTokens,profile:t})),s=R(c,t=>t.tokens);return P({profiles:c,limit:l,filePattern:p,focusFiles:u,candidateIndex:s,profile:{name:"react-component-duplicates"},compare:(t,i)=>y(t,i,r),sort:(t,i)=>i.similarity-t.similarity||t.fileA.localeCompare(i.fileA)||t.componentA.localeCompare(i.componentA)||t.fileB.localeCompare(i.fileB)||t.componentB.localeCompare(i.componentB)})}function y(e,o,r){let n=v(e.tokens,o.tokens);if(n.size<6||!T(n))return null;let l=k(e.tokens,o.tokens);if(l<r)return null;let m=a(n,"component:"),d=a(n,"native:"),p=a(n,"prop:"),u=a(n,"event:"),c=a(n,"binding:"),s=b({sharedComponents:m,sharedNativeTags:d,sharedProps:p,sharedEvents:u,sharedBindings:c});return{fileA:e.file,componentA:e.component,fileB:o.file,componentB:o.component,similarity:l,sharedTokens:f(n),sharedComponents:m,sharedNativeTags:d,sharedProps:p,sharedEvents:u,sharedBindings:c,evidenceClass:s.evidenceClass,actionTier:s.actionTier,evidenceClassReasons:s.reasons,recommendation:s.recommendation,uniqueToA:f(h(e.tokens,o.tokens)).slice(0,25),uniqueToB:f(h(o.tokens,e.tokens)).slice(0,25),locA:e.profile.loc,locB:o.profile.loc}}function T(e){let o=0,r=0;for(let n of e)n.startsWith("component:")&&(o+=1),(n.startsWith("prop:")||n.startsWith("event:")||n.startsWith("native:")||n.startsWith("jsx:"))&&(r+=1);return B([{name:"component",count:o},{name:"shape",count:r}],[{min:{component:1},reason:"shared custom component"},{min:{shape:4},reason:"shared JSX structure"}]).pass}function b(e){return C({genericWords:x,primitiveGroups:[{values:e.sharedNativeTags,reasonPrefix:"shared native tags",bucket:"generic"},{values:e.sharedProps,reasonPrefix:"shared props",bucket:"generic"},{values:e.sharedEvents,reasonPrefix:"shared events",bucket:"generic"}],nameGroups:[{names:e.sharedComponents,label:"shared component",fallbackBucket:"generic"},{names:e.sharedBindings,label:"shared binding",fallbackBucket:"generic"}],recommendation:w})}function w(e){switch(e){case"domain-behavior":case"mixed":return"Review for a shared component or feature-specific UI primitive around the named domain structure.";case"shared-abstraction":return"Review the existing shared component usage first; extract only if duplicated structure remains outside it.";case"generic-workflow-scaffolding":return"Generic structural overlap \u2014 verify intent before consolidating."}}var x=new Set(["actions","app","button","card","children","content","container","dialog","field","form","header","input","item","label","layout","list","modal","page","panel","row","section","shell","table","text","toolbar","ui","value","view","wrapper"]);export{D as a};
|
|
2
|
+
//# sourceMappingURL=chunk-5AAAEZ2Z.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{a as T,c as E,g as L,h as D}from"./chunk-GHXRVCIY.js";import{j as O,o as A}from"./chunk-STBXCPKY.js";import{d as H}from"./chunk-KMVGRIO2.js";import{a as _}from"./chunk-X4O6K47U.js";import{d as C,e as F}from"./chunk-HXXMPYEF.js";import{a as w}from"./chunk-T2FQ4GHD.js";var J=5;function ae(e,t={}){let{base:a="HEAD",minContainment:o=.7,minCallees:r=3,minSiteCoverage:n=.4,maxHelpers:c=Number.POSITIVE_INFINITY,limit:m=20,scanLimit:g}=t,f=t.semantic!==!1,s=t.diffPlan??E(e,{base:a}),l={available:s.note!==T,base:a,changedFiles:s.changedFiles,helpersChecked:0,skipped:[],findings:[]};if(!l.available||s.changedFiles.length===0)return l;let x=new _(e),k=new Set(s.changedFiles),$=new Map(s.renamedFiles.map(i=>[i.to,i.from])),j=t.baseContentAt??L(e.config.projectRoot,a,D(s)),h=Z(x,k,$,j);if(h.length===0)return l;let R=h.slice(0,c);h.length>c&&(l.note=`helper scoring capped at ${c} of ${h.length} new symbols`);let q=x.calleeMap(R,{semantic:f}),B=R.map(i=>({def:i,callees:A((q.get(i.symbolId)??[]).map(p=>p.symbol))})),V=O(e),M,G=()=>(M??=V.calleeIndex({minCallees:Math.min(3,r),scanLimit:g,semantic:f}),M);for(let{def:i,callees:p}of B){let d=C(i.symbol);if(p.size<r){l.skipped.push({helperShortName:d,helperFile:i.relativePath,reason:`fewer than ${r} meaningful callees \u2014 too small to score`});continue}let P=G(),N=Y(p,P);if(N===0){l.skipped.push({helperShortName:d,helperFile:i.relativePath,reason:"helper callee pattern is all project-wide infrastructure \u2014 too generic to score"});continue}let b=Q(e,i.symbolId);if(b.length===0){l.skipped.push({helperShortName:d,helperFile:i.relativePath,reason:"no references yet \u2014 covered by the new-dead check"});continue}l.helpersChecked+=1;let I=K({candidateIndex:P,changed:k,helperCallees:p,helperFile:i.relativePath,helperSymbol:i.symbol,minContainment:o,minSiteCoverage:n,migratedFiles:b});I.length!==0&&(I.sort((u,S)=>z(S.migrationScope)-z(u.migrationScope)||S.containment-u.containment||S.siteCoverage-u.siteCoverage||u.file.localeCompare(S.file)),l.findings.push({helperSymbol:i.symbol,helperShortName:d,helperFile:i.relativePath,helperShape:"specific-callee-cluster",helperCalleeCount:p.size,specificHelperCalleeCount:N,migratedFiles:b.sort(),leftovers:I.slice(0,J)}))}return l.findings.sort((i,p)=>(p.leftovers[0]?.containment??0)-(i.leftovers[0]?.containment??0)||i.helperFile.localeCompare(p.helperFile)),l.findings=l.findings.slice(0,m),l}function K(e){let t=[],a=U(e.helperSymbol,e.helperFile,e.migratedFiles),o=new Set;for(let r of e.helperCallees)for(let n of e.candidateIndex.candidateIndexesByCallee.get(r)??[])o.add(n);for(let r of o){let n=e.candidateIndex.corpus[r];if(n.symbol===e.helperSymbol||e.changed.has(n.file)||n.callees.has(e.helperSymbol))continue;let c=H(e.helperCallees,n.callees);if(c<e.minContainment)continue;let m=[...e.helperCallees].filter(s=>n.callees.has(s)),g=n.callees.size===0?0:m.length/n.callees.size;if(g<e.minSiteCoverage||!m.some(s=>(e.candidateIndex.docFreq.get(s)??0)<=e.candidateIndex.ubiquityThreshold))continue;let f=W(a,n.symbol,n.file);t.push({symbol:n.symbol,shortName:C(n.symbol),file:n.file,...f,containment:c,siteCoverage:g,uniqueSiteCalleeCount:Math.max(0,n.callees.size-m.length),sharedCallees:m.map(C).sort()})}return t}function z(e){return e==="same-scope"?2:e==="unknown"?1:0}function U(e,t,a){let o=new Set([...y(t),...v(F(e))]);for(let r of a)for(let n of y(r))o.add(n);return o}function W(e,t,a){let o=new Set([...y(a),...v(F(t))]);if(e.size===0||o.size===0)return{migrationScope:"unknown",migrationScopeReasons:["insufficient path/name tokens to infer migration scope"]};let r=[...o].filter(n=>e.has(n)).sort();return r.length>0?{migrationScope:"same-scope",migrationScopeReasons:[`shares migration-scope token(s): ${r.slice(0,5).join(", ")}`]}:{migrationScope:"possible-subtype",migrationScopeReasons:["no path/name tokens shared with the helper or already migrated files"]}}var X=new Set(["app","apps","common","component","components","helper","helpers","index","lib","package","packages","page","pages","route","routes","service","services","shared","spec","src","test","tests","util","utils"]);function y(e){return v(e.replace(/\.[^.]+$/,""))}function v(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").toLowerCase().split(/[^a-z0-9]+/).filter(t=>t.length>1&&!X.has(t))}function Y(e,t){let a=0;for(let o of e)(t.docFreq.get(o)??0)<=t.ubiquityThreshold&&(a+=1);return a}function Z(e,t,a,o){return e.productionCallableDefinitions({files:[...t],requireFunctionLikeSymbol:!0}).filter(r=>{if(!t.has(r.relativePath))return!1;let n=a.get(r.relativePath)??r.relativePath,c=o(n);return c===null||!new RegExp(`\\b${w(r.leaf)}\\b`).test(c)})}function Q(e,t){return e.all(`SELECT DISTINCT ref_d.relative_path
|
|
2
|
+
FROM mentions m
|
|
3
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
4
|
+
JOIN documents ref_d ON c.document_id = ref_d.id
|
|
5
|
+
WHERE m.symbol_id = ?
|
|
6
|
+
AND m.role != 1
|
|
7
|
+
${e.pathExclusionsFor("ref_d")}`,t).map(o=>o.relative_path)}export{ae as a};
|
|
8
|
+
//# sourceMappingURL=chunk-6Q6OFLFQ.js.map
|