scip-query 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +1 -0
- package/dist/augment-vue-worker.js +1 -1
- package/dist/{chunk-2DBY4MO7.js → chunk-24ET4VLC.js} +2 -2
- package/dist/chunk-2NA6TYP4.js +120 -0
- package/dist/{chunk-XKWEMFHP.js → chunk-2WCXKANA.js} +2 -2
- package/dist/{chunk-LL5NQB5V.js → chunk-34MLC6UI.js} +2 -2
- package/dist/chunk-35NLDRZC.js +2 -0
- package/dist/{chunk-MNRKD3WP.js → chunk-3WLRW5TC.js} +2 -2
- package/dist/{chunk-SW7LKHRU.js → chunk-4BU54UJG.js} +2 -2
- package/dist/{chunk-T4P27T6S.js → chunk-4CZJ4YJB.js} +2 -2
- package/dist/{chunk-3CJXFMR5.js → chunk-4FMT4HPC.js} +2 -2
- package/dist/{chunk-J7IMQRCU.js → chunk-53SUJOJA.js} +2 -2
- package/dist/{chunk-27YDE22N.js → chunk-5GOBZI34.js} +2 -2
- package/dist/{chunk-4FLF7BHJ.js → chunk-5OZCNAVM.js} +2 -2
- package/dist/chunk-5TEUKVSM.js +2 -0
- package/dist/{chunk-GTANVH72.js → chunk-5W2VAEVR.js} +2 -2
- package/dist/{chunk-43QUXX3E.js → chunk-63P42UR6.js} +2 -2
- package/dist/{chunk-OQFPCIXO.js → chunk-64QITTX7.js} +2 -2
- package/dist/{chunk-P4L5QQT5.js → chunk-6O5JOS7T.js} +2 -2
- package/dist/chunk-6PKO2TNZ.js +2 -0
- package/dist/{chunk-OSBLECSI.js → chunk-7SGOWD2Y.js} +2 -2
- package/dist/chunk-7TJJY2C3.js +2 -0
- package/dist/{chunk-K3UVTL3J.js → chunk-AEM24WSF.js} +2 -2
- package/dist/{chunk-PV3GKBO5.js → chunk-AGTATREV.js} +2 -2
- package/dist/chunk-AOSFSYEA.js +20 -0
- package/dist/{chunk-VCRMI56V.js → chunk-APLNTJPJ.js} +2 -2
- package/dist/{chunk-7XP7ZRSI.js → chunk-AYRHVJXW.js} +2 -2
- package/dist/chunk-B2WQKQKP.js +3 -0
- package/dist/{chunk-SWJEREML.js → chunk-BBBKPOIT.js} +2 -2
- package/dist/{chunk-OTTHMUMV.js → chunk-BCMOTIB6.js} +2 -2
- package/dist/chunk-BMTBVMA3.js +10 -0
- package/dist/{chunk-J7WYG63U.js → chunk-C3KCSAQ4.js} +2 -2
- package/dist/{chunk-5CJ6AQN7.js → chunk-CAKPEQZB.js} +2 -2
- package/dist/{chunk-UWR52GNZ.js → chunk-CIYUFF24.js} +2 -2
- package/dist/{chunk-ABDXTPCT.js → chunk-CKFMZE77.js} +2 -2
- package/dist/chunk-DCDOGW32.js +2 -0
- package/dist/{chunk-ODH4FT3P.js → chunk-DFQNE73Y.js} +2 -2
- package/dist/chunk-DO775SYA.js +2 -0
- package/dist/chunk-DRH3AD7W.js +4 -0
- package/dist/chunk-DZXFZAZO.js +16 -0
- package/dist/chunk-E3KWOHH7.js +5 -0
- package/dist/chunk-EMIIOOTM.js +38 -0
- package/dist/chunk-ESNRT7QN.js +927 -0
- package/dist/{chunk-AWYKDRYV.js → chunk-FB6IKAKZ.js} +2 -2
- package/dist/{chunk-BGUYAA3Q.js → chunk-FBUNGRKI.js} +2 -2
- package/dist/{chunk-M2TRDR25.js → chunk-FC5K7T35.js} +1 -1
- package/dist/{chunk-GWCW25ON.js → chunk-FHLYJVXF.js} +2 -2
- package/dist/{chunk-IG6X65MG.js → chunk-FRXB74RQ.js} +2 -2
- package/dist/{chunk-IKMOYFUM.js → chunk-FTRNGQGR.js} +2 -2
- package/dist/{chunk-NX2YAXVQ.js → chunk-FUFNRZFJ.js} +2 -2
- package/dist/{chunk-JLZUM476.js → chunk-GAE7WCBK.js} +2 -2
- package/dist/chunk-GIHVWNKQ.js +18 -0
- package/dist/{chunk-MPBN5DO4.js → chunk-HCS5LB6U.js} +2 -2
- package/dist/{chunk-6JSTKSZH.js → chunk-HFBNIIZX.js} +2 -2
- package/dist/{chunk-JHK2DMUQ.js → chunk-HGFDYOVB.js} +1 -1
- package/dist/chunk-IOOCKVUA.js +6 -0
- package/dist/{chunk-4L4X66GE.js → chunk-J4MYRIYT.js} +2 -2
- package/dist/{chunk-TAB7AWKO.js → chunk-J5XJWCB3.js} +2 -2
- package/dist/{chunk-POGZSZPX.js → chunk-JBZXJXIS.js} +2 -2
- package/dist/chunk-JJZRS2OP.js +5 -0
- package/dist/chunk-KC2IFAAU.js +3 -0
- package/dist/{chunk-3M2UCPFS.js → chunk-KHE7J5ZN.js} +1 -1
- package/dist/{chunk-4XTPZ5CR.js → chunk-KMOMNTB4.js} +2 -2
- package/dist/chunk-KMUFGAIK.js +2 -0
- package/dist/chunk-LF5CIKWZ.js +26 -0
- package/dist/chunk-LM72NQ7T.js +3 -0
- package/dist/{chunk-QPF7CS5W.js → chunk-LQUDSHLB.js} +2 -2
- package/dist/chunk-MP43RX4O.js +67 -0
- package/dist/{chunk-D5OXYOJP.js → chunk-MQ2B33LQ.js} +1 -1
- package/dist/{chunk-WA64GKWB.js → chunk-NH7WNNQC.js} +3 -3
- package/dist/{chunk-HOZ3IXZ5.js → chunk-NTOBQK5H.js} +2 -2
- package/dist/{chunk-SUYCF4SX.js → chunk-OLG2YPLS.js} +2 -2
- package/dist/{chunk-O5Y3ISO3.js → chunk-OOUJBAKJ.js} +2 -2
- package/dist/{chunk-U244OVE6.js → chunk-OQ6TCHBB.js} +2 -2
- package/dist/{chunk-5GAUXLOE.js → chunk-PNESKY2Z.js} +2 -2
- package/dist/chunk-PYMZU5EG.js +2 -0
- package/dist/chunk-Q2WEWIKX.js +4 -0
- package/dist/chunk-QHKXGMOI.js +3 -0
- package/dist/{chunk-VXDMXZKC.js → chunk-RPEA7P5Z.js} +2 -2
- package/dist/{chunk-K65T4TJS.js → chunk-SJ6XSCG7.js} +2 -2
- package/dist/{chunk-LADYDOS5.js → chunk-SSXEYWN3.js} +2 -2
- package/dist/chunk-SYGAA54M.js +2 -0
- package/dist/{chunk-H4T2AST4.js → chunk-TYEGFDOP.js} +2 -2
- package/dist/chunk-UJKZQLDB.js +2 -0
- package/dist/{chunk-PZV2PGBR.js → chunk-US44MEVU.js} +2 -2
- package/dist/{chunk-EJ65IVPV.js → chunk-V5WBVF6K.js} +2 -2
- package/dist/{chunk-AV54WZUK.js → chunk-V7J4A3AH.js} +2 -2
- package/dist/{chunk-45QWQSWS.js → chunk-VIKEPD4D.js} +2 -2
- package/dist/{chunk-TLTLJ4SW.js → chunk-WAU7HVDI.js} +2 -2
- package/dist/chunk-WCZAABYF.js +2 -0
- package/dist/{chunk-FMD46HAG.js → chunk-WFRET75Z.js} +2 -2
- package/dist/chunk-WWCZCH7W.js +3 -0
- package/dist/chunk-XBN5VO53.js +2 -0
- package/dist/{chunk-35TZERMO.js → chunk-XCPE3G75.js} +2 -2
- package/dist/chunk-XYBNOILR.js +2 -0
- package/dist/{chunk-BAMVG4WQ.js → chunk-XZXUMGAA.js} +2 -2
- package/dist/{chunk-MN54AGZ3.js → chunk-YCSTKIYU.js} +2 -2
- package/dist/{chunk-CMLHZWRS.js → chunk-YGQBJUS6.js} +2 -2
- package/dist/{chunk-7ROLM67J.js → chunk-YILKXTIY.js} +2 -2
- package/dist/{chunk-YMFHC5J2.js → chunk-ZJGZCBYT.js} +2 -2
- package/dist/{chunk-D5F3IQYP.js → chunk-ZNK6K3LB.js} +2 -2
- package/dist/cli.js +2 -2
- package/dist/{command-descriptors-AQWWJNTT.js → command-descriptors-3EJHQLQZ.js} +173 -167
- package/dist/{config-types-70s7NxKB.d.ts → config-types-BA3xLCfG.d.ts} +28 -1
- package/dist/{db-BBmJ0v3b.d.ts → db-CzA-9_rL.d.ts} +6 -18
- package/dist/direct-navigation-C2A44KFT.js +3 -0
- package/dist/{health-CWpFL_6z.d.ts → health-DYy13GAe.d.ts} +3 -1
- package/dist/index.d.ts +23 -41
- package/dist/index.js +1 -1
- package/dist/postinstall.js +1 -1
- package/dist/queries/affected.d.ts +2 -2
- package/dist/queries/affected.js +1 -1
- package/dist/queries/architecture.d.ts +83 -0
- package/dist/queries/architecture.js +2 -0
- 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 +2 -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 +2 -2
- package/dist/queries/complexity-hotspots.js +1 -1
- package/dist/queries/complexity.d.ts +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dist/queries/dead.js +1 -1
- package/dist/queries/decorative-checkers.d.ts +2 -2
- package/dist/queries/decorative-checkers.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 +5 -3
- package/dist/queries/diff-gate.js +1 -1
- package/dist/queries/diff-impact.d.ts +2 -2
- package/dist/queries/diff-impact.js +1 -1
- package/dist/queries/doc-drift.d.ts +2 -2
- package/dist/queries/doc-drift.js +1 -1
- package/dist/queries/drift.d.ts +27 -10
- package/dist/queries/drift.js +1 -1
- package/dist/queries/duplicate-bodies.d.ts +2 -2
- package/dist/queries/duplicate-bodies.js +1 -1
- 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 +2 -2
- 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 +2 -2
- package/dist/queries/incomplete-migration.js +1 -1
- package/dist/queries/index.d.ts +5 -4
- 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/not-implemented.d.ts +2 -2
- package/dist/queries/not-implemented.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 +2 -2
- package/dist/queries/passthrough-candidates.js +1 -1
- package/dist/queries/plan-context.d.ts +2 -2
- package/dist/queries/plan-context.js +1 -1
- package/dist/queries/react-component-duplicates.d.ts +2 -2
- package/dist/queries/react-component-duplicates.js +1 -1
- package/dist/queries/react-hook-candidates.d.ts +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dist/queries/similar-signatures.js +1 -1
- package/dist/queries/similar.d.ts +2 -2
- 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/test-quality.d.ts +2 -2
- package/dist/queries/test-quality.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 +2 -2
- package/dist/queries/twin-ab.js +1 -1
- package/dist/queries/twin-drift.d.ts +2 -2
- package/dist/queries/twin-drift.js +1 -1
- 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 +2 -2
- package/dist/queries/vue-component-duplicates.js +1 -1
- package/dist/queries/vue-composable-candidates.d.ts +2 -2
- package/dist/queries/vue-composable-candidates.js +1 -1
- package/dist/queries/vue-large-view-pressure.d.ts +2 -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 +24 -24
- package/dist/reindex.d.ts +12 -10
- package/dist/reindex.js +38 -38
- package/dist/runtime.d.ts +10 -9
- package/dist/runtime.js +2 -1
- package/dist/rust-semantic-session-server.js +1 -1
- package/dist/rust-semantic-session-worker.js +1 -1
- package/dist/rust-semantic-worker.js +1 -1
- package/dist/{scip-cli-CoMzb7Zu.d.ts → scip-cli-1bVKJgXi.d.ts} +1 -1
- package/dist/watch-server.js +7 -6
- package/docs/AI_FAILURE_MODES.md +1 -0
- package/docs/COMMAND_REFERENCE.md +3 -2
- package/docs/DETECTOR_GUIDE.md +5 -3
- package/docs/analyzer-inventory.md +16 -6
- package/docs/analyzer-validation-ledger.md +12 -1
- package/docs/architecture-coherence-vision.md +219 -0
- package/package.json +5 -1
- package/skills/_shared/SKILL.md +4 -3
- package/skills/scip-conductor/SKILL.md +1 -1
- package/skills/scip-directory-architecture/SKILL.md +116 -2
- package/skills/scip-maintainability/SKILL.md +3 -3
- package/skills/scip-query/SKILL.md +1 -1
- package/skills/scip-twin-drift/SKILL.md +1 -1
- package/skills/scip-verify/SKILL.md +1 -1
- package/dist/chunk-2GX3TNOW.js +0 -38
- package/dist/chunk-45XOH33S.js +0 -2
- package/dist/chunk-4MFMTEJ4.js +0 -5
- package/dist/chunk-BECOMXAL.js +0 -2
- package/dist/chunk-BJJHBKEC.js +0 -2
- package/dist/chunk-DDGO34I2.js +0 -26
- package/dist/chunk-DUKRAHV2.js +0 -2
- package/dist/chunk-EMEXMHOP.js +0 -7
- package/dist/chunk-GWNE2WJN.js +0 -3
- package/dist/chunk-H4JNB7RT.js +0 -3
- package/dist/chunk-L2RE5P3X.js +0 -2
- package/dist/chunk-L2TSLMPT.js +0 -5
- package/dist/chunk-NQBMGFFD.js +0 -2
- package/dist/chunk-O5A7BTMA.js +0 -3
- package/dist/chunk-OINSINYW.js +0 -2
- package/dist/chunk-OM6JHEW3.js +0 -16
- package/dist/chunk-OUXPJ4H5.js +0 -3
- package/dist/chunk-OWXNDSG3.js +0 -2
- package/dist/chunk-Q4UM4JJP.js +0 -2
- package/dist/chunk-QEIGJJBC.js +0 -20
- package/dist/chunk-R4VPIS4D.js +0 -10
- package/dist/chunk-RDX6WWHN.js +0 -4
- package/dist/chunk-RUQE7DZT.js +0 -2
- package/dist/chunk-S43DIBME.js +0 -18
- package/dist/chunk-SALRDXWM.js +0 -121
- package/dist/chunk-SMBIGBGN.js +0 -67
- package/dist/chunk-VQWDZ34M.js +0 -928
- package/dist/chunk-W3557RPL.js +0 -3
- package/dist/chunk-W3SKYOTF.js +0 -2
- package/dist/chunk-XEEQX5X3.js +0 -3
- package/dist/direct-navigation-K3CTVVBU.js +0 -3
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Architecture Coherence Vision
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
scip-query should help a maintainer answer two different questions:
|
|
6
|
+
|
|
7
|
+
1. What architecture does this codebase actually have?
|
|
8
|
+
2. Where does the implementation contradict the architecture the project intends to preserve?
|
|
9
|
+
|
|
10
|
+
The dependency graph can answer neither question alone. It records which files rely on which other files. Architectural judgment connects those facts to the real responsibilities, public contracts, runtime boundaries, and maintenance work that gave the code its structure.
|
|
11
|
+
|
|
12
|
+
The product vision is therefore a combination of:
|
|
13
|
+
|
|
14
|
+
- an `architecture` query that measures declared boundaries and dependency rules;
|
|
15
|
+
- a directory-architecture skill that helps an agent discover, name, test, and gradually enforce those rules;
|
|
16
|
+
- drift and health integrations that expose architectural changes without pretending every unusual import is a defect.
|
|
17
|
+
|
|
18
|
+
## Vocabulary
|
|
19
|
+
|
|
20
|
+
An architectural boundary is a named group of code with one stable reason to change, such as a domain model, rendering subsystem, persistence adapter, compiler frontend, or deployable service. A folder often represents a boundary, but a folder is only evidence of one: the decisive fact is the responsibility its files jointly serve.
|
|
21
|
+
|
|
22
|
+
A dependency edge is a directed relationship from code that relies on something to the code it relies on. For an import, `A -> B` means file A imports file B. The direction matters because changes to B can force changes in A.
|
|
23
|
+
|
|
24
|
+
A boundary edge is the same relationship after file edges are grouped by their architectural boundaries. Ten imports from UI files into domain files form one `ui -> domain` boundary edge with ten pieces of file-level evidence.
|
|
25
|
+
|
|
26
|
+
An allowed edge is a boundary dependency that agrees with a declared rule. A forbidden edge is an actual dependency that contradicts a declared rule about which responsibilities may rely on which others. Files being far apart or living under different directories does not by itself make the edge forbidden.
|
|
27
|
+
|
|
28
|
+
A reciprocal dependency is a pair of boundary edges in both directions, such as `source -> parser` and `parser -> source`. It is a review signal because neither boundary can change independently, but it can be intentional when the named boundaries are really one subsystem or meet through a deliberately shared contract.
|
|
29
|
+
|
|
30
|
+
A strongly connected component is a group of boundaries where every member can reach every other member through dependency edges. Its essential consequence is mutual change pressure: no member is directionally independent of the group. A component with many boundaries is evidence that the current names may not describe real separation.
|
|
31
|
+
|
|
32
|
+
A cycle-break candidate is a boundary edge inside a dependency cycle whose small amount of file-level evidence makes it a plausible place to inspect first. It is not automatically the correct edge to remove; a single import can expose either an accidental shortcut or a legitimate contract that the boundary model failed to name.
|
|
33
|
+
|
|
34
|
+
An architecture policy is the project-owned configuration that names boundaries and records dependency directions the maintainers are prepared to defend. Its rules are stronger than inferred folder conventions because the project explicitly chose them.
|
|
35
|
+
|
|
36
|
+
An architecture ratchet is an enforcement rule that permits recorded existing debt while preventing new violations. It lets a large codebase improve incrementally without requiring a speculative rewrite before the policy becomes useful.
|
|
37
|
+
|
|
38
|
+
Architectural coherence is the degree to which actual dependencies, named responsibilities, and declared dependency rules describe the same system. The tool should report the evidence needed to improve that alignment, not reduce coherence to a single score.
|
|
39
|
+
|
|
40
|
+
## Why `drift` Is Not Enough
|
|
41
|
+
|
|
42
|
+
Drift is movement away from a reference state or established pattern. A system can be statically incoherent without having changed recently, and it can change while remaining coherent. Therefore architecture needs a first-class report rather than being hidden inside `drift`.
|
|
43
|
+
|
|
44
|
+
`scip-query architecture` owns the complete boundary graph and policy
|
|
45
|
+
evaluation. `scip-query drift --architecture` reuses that report to show
|
|
46
|
+
direct declared violations together with mapping coverage and report-only
|
|
47
|
+
signals; it does not maintain a second policy engine.
|
|
48
|
+
|
|
49
|
+
Before this work, the source-layer table in
|
|
50
|
+
`src/queries/cleanup/drift-policy.ts` embedded repository-specific knowledge in
|
|
51
|
+
a general-purpose command. An unrelated repository using folders such as
|
|
52
|
+
`src/core` and `src/runtime` could therefore inherit scip-query's rules. That
|
|
53
|
+
table has now been removed: drift consumes only explicit project
|
|
54
|
+
configuration, and an unconfigured repository receives no architecture
|
|
55
|
+
violations.
|
|
56
|
+
|
|
57
|
+
## Configuration Model
|
|
58
|
+
|
|
59
|
+
The first configuration shape should be small enough to understand without learning a policy language:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"architecture": {
|
|
64
|
+
"boundaries": [
|
|
65
|
+
{ "name": "domain", "paths": ["src/domain/**"] },
|
|
66
|
+
{ "name": "source", "paths": ["src/source/**"] },
|
|
67
|
+
{ "name": "runtime", "paths": ["src/runtime/**"] }
|
|
68
|
+
],
|
|
69
|
+
"allowedDependencies": {
|
|
70
|
+
"domain": [],
|
|
71
|
+
"source": ["domain"],
|
|
72
|
+
"runtime": ["domain", "source"]
|
|
73
|
+
},
|
|
74
|
+
"requireCompletePolicy": true,
|
|
75
|
+
"requireAcyclic": true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
A boundary row names code; it does not yet prohibit anything. An `allowedDependencies` row is closed: when a row exists for `source`, every cross-boundary dependency not listed in that row is forbidden. A missing row means the project has not made a rule for that boundary yet. Same-boundary dependencies remain allowed.
|
|
81
|
+
|
|
82
|
+
This distinction lets a large repository describe mature boundaries first while leaving emerging or disputed areas in discovery mode.
|
|
83
|
+
|
|
84
|
+
`requireCompletePolicy` turns that gradual-discovery model into a finished
|
|
85
|
+
contract: every configured boundary must have a closed row, including an empty
|
|
86
|
+
row for a boundary that may depend on nothing. `requireAcyclic` independently
|
|
87
|
+
forbids multi-boundary strongly connected components. A project should enable
|
|
88
|
+
both only after the observed graph has been classified and repaired.
|
|
89
|
+
|
|
90
|
+
## What the Analyzer Should Report
|
|
91
|
+
|
|
92
|
+
The report should preserve both policy truth and graph evidence:
|
|
93
|
+
|
|
94
|
+
- mapped, unmapped, and ambiguously mapped files;
|
|
95
|
+
- boundary edges with importer count, imported-file count, total file-edge count, and representative file edges;
|
|
96
|
+
- forbidden edges, grouped by boundary pair rather than emitted as a flood of individual imports;
|
|
97
|
+
- reciprocal boundary pairs;
|
|
98
|
+
- strongly connected boundary components;
|
|
99
|
+
- the narrowest internal edges to inspect first for each component;
|
|
100
|
+
- policy coverage: which boundaries have closed dependency rows and which remain descriptive only.
|
|
101
|
+
- resolved `export ... from` dependencies as well as ordinary imports, so
|
|
102
|
+
published barrel and package surfaces are governed;
|
|
103
|
+
|
|
104
|
+
The output tiers should remain explicit:
|
|
105
|
+
|
|
106
|
+
- **Direct finding:** an actual edge contradicts a declared rule, or a declared acyclicity rule is violated.
|
|
107
|
+
- **Signal:** reciprocity, a large connected component, low policy coverage, an unmapped file, or a narrow cycle-break candidate.
|
|
108
|
+
|
|
109
|
+
Inferred signals should not reduce health scores or block diffs until external calibration shows that acting on them reliably improves real codebases.
|
|
110
|
+
|
|
111
|
+
## Applying This to an Existing Large Codebase
|
|
112
|
+
|
|
113
|
+
The tool cannot discover the “best architecture” by optimizing graph shape. The best available architecture is the clearest model that preserves the system's real responsibilities and necessary behavior while reducing accidental change pressure. Finding it requires a staged investigation.
|
|
114
|
+
|
|
115
|
+
### 1. Inventory the system's referents
|
|
116
|
+
|
|
117
|
+
Read the repository guidance, package manifests, deployable entry points, routes, public exports, databases, message boundaries, tests, and build graph. Use scip-query to map consumers, dependencies, change surfaces, cycles, locality candidates, and historical co-change.
|
|
118
|
+
|
|
119
|
+
This identifies what the code actually does and which units already behave as maintenance units.
|
|
120
|
+
|
|
121
|
+
### 2. Name candidate boundaries
|
|
122
|
+
|
|
123
|
+
Do not assume every top-level directory is a layer. A layer is a responsibility ordered by dependency direction, such as presentation over application over domain. A subsystem is a responsibility that owns an end-to-end capability, such as authentication or a compiler. A package is a publication or build unit. A service is an independently running unit.
|
|
124
|
+
|
|
125
|
+
The architecture model may contain all four. The useful name is the one that predicts why its code changes and what it may depend on.
|
|
126
|
+
|
|
127
|
+
### 3. Classify boundary maturity
|
|
128
|
+
|
|
129
|
+
- A mature boundary is repeatedly expressed by code, documentation, tests, entry points, ownership, or history.
|
|
130
|
+
- An emerging boundary has a coherent responsibility but inconsistent placement or dependencies.
|
|
131
|
+
- An accidental boundary is mainly a convenience bucket, legacy pile, generated directory, or recent edit cluster.
|
|
132
|
+
|
|
133
|
+
Only mature boundaries should receive closed dependency rules initially.
|
|
134
|
+
|
|
135
|
+
### 4. Build a descriptive model first
|
|
136
|
+
|
|
137
|
+
Add boundary path patterns without `allowedDependencies` rows. Run `scip-query architecture --json` to inspect mapping coverage, actual boundary edges, reciprocal pairs, and connected components.
|
|
138
|
+
|
|
139
|
+
Revise names and path membership when the graph reveals that a supposed boundary has no independent responsibility or that one responsibility is split across several folders.
|
|
140
|
+
|
|
141
|
+
### 5. Declare the rules supported by evidence
|
|
142
|
+
|
|
143
|
+
For each mature boundary, state which other boundaries it is allowed to depend on and why. Record uncertain edges as unresolved decisions instead of silently allowing the entire current graph.
|
|
144
|
+
|
|
145
|
+
Run the report again. A forbidden edge is now a testable disagreement between implementation and policy, not the tool's opinion about directory distance.
|
|
146
|
+
|
|
147
|
+
### 6. Baseline and ratchet
|
|
148
|
+
|
|
149
|
+
Record reviewed existing violations with `scip-query health
|
|
150
|
+
--write-baseline`. Architecture identities name a forbidden boundary pair or
|
|
151
|
+
an explicitly forbidden boundary cycle, so moving a representative file does
|
|
152
|
+
not churn the ratchet. The default `scip-query diff-gate` architecture check
|
|
153
|
+
then rejects new identities while preserving visibility into recorded debt.
|
|
154
|
+
This turns architecture from a one-time diagram into a maintained contract.
|
|
155
|
+
|
|
156
|
+
### 7. Migrate narrow seams
|
|
157
|
+
|
|
158
|
+
Start with a narrow edge whose few file dependencies cross a mature rule. Determine whether the right repair is to move code, invert a dependency, extract a genuinely shared contract, combine falsely separated boundaries, or revise the policy.
|
|
159
|
+
|
|
160
|
+
Verify each slice with tests, typechecking, incomplete-migration checks, architecture analysis, and diff-gate before taking the next one.
|
|
161
|
+
|
|
162
|
+
## Example: Vega 2.0
|
|
163
|
+
|
|
164
|
+
For a codebase the size of Vega 2.0, the first pass should not invent a universal stack of layers. It should:
|
|
165
|
+
|
|
166
|
+
1. identify workspace packages, applications, servers, public entry points, data stores, and major feature or compiler/rendering subsystems;
|
|
167
|
+
2. map actual dependency traffic between those units;
|
|
168
|
+
3. read the architecture and ownership claims already present in docs and package surfaces;
|
|
169
|
+
4. classify candidate boundaries as mature, emerging, or accidental;
|
|
170
|
+
5. configure the mature boundaries descriptively;
|
|
171
|
+
6. inspect reciprocal pairs and large connected components with their file-edge breadth;
|
|
172
|
+
7. close dependency rows only where the intended direction is supported;
|
|
173
|
+
8. baseline existing violations and prevent new ones;
|
|
174
|
+
9. migrate one narrow, high-confidence seam at a time.
|
|
175
|
+
|
|
176
|
+
The initial result may be a mixture of layers and subsystems. That is preferable to forcing a neat diagram that contradicts the software. The model becomes stronger as verified migrations and maintenance history provide new facts.
|
|
177
|
+
|
|
178
|
+
## Delivery Sequence
|
|
179
|
+
|
|
180
|
+
### Slice 1: explicit measurement — implemented
|
|
181
|
+
|
|
182
|
+
- Add architecture configuration types and validation.
|
|
183
|
+
- Extract the reusable strongly-connected-component algorithm already embedded in `deep-chains`.
|
|
184
|
+
- Add a pure architecture graph analyzer and `scip-query architecture`.
|
|
185
|
+
- Extend the directory-architecture skill with the discover, declare, measure, and ratchet workflow.
|
|
186
|
+
- Keep architecture outside health scoring and diff-gate blocking.
|
|
187
|
+
|
|
188
|
+
### Slice 2: replace implicit drift policy — implemented
|
|
189
|
+
|
|
190
|
+
- Move scip-query's source-boundary rules into its `.scipquery.json`.
|
|
191
|
+
- Make drift consume architecture findings instead of repository-specific hardcoded folder rules.
|
|
192
|
+
- Add `drift --architecture` as a summary view.
|
|
193
|
+
- Preserve unused-import drift and keep sibling-pattern deviation opt-in.
|
|
194
|
+
|
|
195
|
+
### Slice 3: baselines and enforcement — implemented locally; external calibration remains
|
|
196
|
+
|
|
197
|
+
- Give architecture findings stable identities.
|
|
198
|
+
- Add report-only health visibility.
|
|
199
|
+
- Add a narrow default diff-gate ratchet for newly introduced declared violations, backed by the shared health baseline.
|
|
200
|
+
- Calibrate on scip-query, Vega 2.0, Stable Management, and structurally different external repositories before any score deduction.
|
|
201
|
+
|
|
202
|
+
### Slice 4: discovery assistance
|
|
203
|
+
|
|
204
|
+
- Add candidate-boundary evidence that combines paths, entry points, public surfaces, dependency neighborhoods, and co-change history.
|
|
205
|
+
- Have the skill produce a reviewable architecture draft, never silently write closed rules.
|
|
206
|
+
- Measure whether suggested boundaries and repairs survive maintainer review and reduce future cross-boundary churn.
|
|
207
|
+
|
|
208
|
+
## Success Criteria
|
|
209
|
+
|
|
210
|
+
The architecture feature is effective when:
|
|
211
|
+
|
|
212
|
+
- an unconfigured repository never inherits scip-query-specific rules;
|
|
213
|
+
- a configured forbidden edge is reported with concrete import evidence;
|
|
214
|
+
- broad and narrow boundary edges are distinguishable;
|
|
215
|
+
- large cycles are summarized without flooding the user;
|
|
216
|
+
- the agent can explain why each proposed boundary exists in the running system;
|
|
217
|
+
- existing debt can be ratcheted without a rewrite;
|
|
218
|
+
- acting on a recommendation improves ownership or dependency direction in externally reviewed codebases;
|
|
219
|
+
- the tool is willing to say “the policy is incomplete” instead of manufacturing certainty.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scip-query",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "Evidence and verification for AI coding agents: map code, reuse concepts, finish migrations, and gate diffs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"import": "./dist/queries/affected.js",
|
|
34
34
|
"types": "./dist/queries/affected.d.ts"
|
|
35
35
|
},
|
|
36
|
+
"./queries/architecture": {
|
|
37
|
+
"import": "./dist/queries/architecture.js",
|
|
38
|
+
"types": "./dist/queries/architecture.d.ts"
|
|
39
|
+
},
|
|
36
40
|
"./queries/bottlenecks": {
|
|
37
41
|
"import": "./dist/queries/bottlenecks.js",
|
|
38
42
|
"types": "./dist/queries/bottlenecks.d.ts"
|
package/skills/_shared/SKILL.md
CHANGED
|
@@ -110,7 +110,7 @@ scip-query cleanup-apply # Apply a compiler-verified cleanup-plan batch to the w
|
|
|
110
110
|
scip-query recent-duplicates # Directional duplicate candidates: recent code that re-implements established callable, React, or Vue code
|
|
111
111
|
scip-query doc-drift [doc] # Stale-doc candidates: code the doc references or co-changed with kept changing after the doc stopped
|
|
112
112
|
scip-query unused-params # Speculative-generality candidates: trailing parameters no body ever uses (TS/JS)
|
|
113
|
-
scip-query drift [module] # Detect
|
|
113
|
+
scip-query drift [module] # Detect drift candidates: unused imports and declared architecture violations; pass --architecture for boundary context
|
|
114
114
|
scip-query wrapper-candidates # Find heuristic wrapper candidates only called by one consumer (high false-positive rate on codebases with intentional layering/ambient types — treat as exploration, not findings)
|
|
115
115
|
scip-query passthrough-candidates # Find heuristic passthrough candidates that forward to one callee
|
|
116
116
|
scip-query stale-abstractions # Find heuristic stale abstraction candidates with 0-1 consumers (high false-positive rate on codebases with intentional layering/ambient types — treat as exploration, not findings)
|
|
@@ -134,6 +134,7 @@ scip-query fan-in [symbol] # Count files referencing an exact symbol; top JSON r
|
|
|
134
134
|
scip-query fan-out [file] # How many external symbols a file uses (or top fan-out across codebase)
|
|
135
135
|
scip-query coupling [file1] [file2] # Coupling between two files, or top coupled pairs in codebase
|
|
136
136
|
scip-query cycles # Detect circular dependency chains between files
|
|
137
|
+
scip-query architecture # Evaluate project-owned architectural boundaries and dependency rules
|
|
137
138
|
scip-query bottlenecks # Find coupling hubs: high fan-in AND high fan-out
|
|
138
139
|
scip-query deep-chains # Find the longest condensed dependency-component chains
|
|
139
140
|
scip-query call-graph <symbol> # Show incoming callers and outgoing callees for a symbol
|
|
@@ -145,7 +146,7 @@ scip-query call-graph <symbol> # Show incoming callers and outgoing callees for
|
|
|
145
146
|
scip-query affected <symbol> # Transitive closure of symbols that could break if this symbol changes
|
|
146
147
|
scip-query change-surface <file> # Pre-change briefing: exports, consumers, and blast-radius risk
|
|
147
148
|
scip-query co-change [file] # Files that change together in git history without a dependency edge — hidden coupling candidates
|
|
148
|
-
scip-query diff-gate # Gate the current diff:
|
|
149
|
+
scip-query diff-gate # Gate the current diff: architecture regressions plus echo, migration, coordination, doc-drift, unused-param, and new-dead candidates; exit 1 on blocking findings
|
|
149
150
|
scip-query incomplete-migration # Partially-completed extraction candidates: new helpers in the diff wired into some sites while similar un-migrated sites remain
|
|
150
151
|
scip-query diff-impact # Compute changed symbols and downstream consumers from current git diff
|
|
151
152
|
```
|
|
@@ -211,7 +212,7 @@ measured precision, not by volume:
|
|
|
211
212
|
|
|
212
213
|
## Diff Gate Checks
|
|
213
214
|
|
|
214
|
-
`diff-gate`
|
|
215
|
+
`diff-gate` recognizes ten checks (`--skip <check>` accepts any of these): `echo` (recent-duplicate-style echoes in the diff), `incomplete-migration`, `co-change-partner` (missing historically-paired file), `twin-partner` (advisory — unedited same-name twin), `coverage-contract` (a configured `coverageContracts` enumeration drifted from its ground truth — see `scip-setup`), `architecture` (a declared boundary violation absent from the shared baseline), `doc-reference` (uncited or stale doc claim), `unused-params`, `new-dead` (dead code introduced by this diff), and `baseline` (only with `--baseline`: compares all non-architecture health identities against the committed `.scipquery-baseline.json`, distinct from `health --baseline`). The architecture check runs by default only when enforceable architecture rules and a baseline exist; it uses that same file without running the full health suite. Findings print grouped under a `Root-cause groups (N):` header before the flat list — a group's remediation usually clears every finding under it, and the same remediation may then repeat in the flat list below; that repetition is expected, not a separate issue. Baseline-backed findings additionally carry an `actionTier`: `direct` (act on this finding alone), `signal` (corroborating evidence — read before acting), `support` (context only).
|
|
215
216
|
|
|
216
217
|
## Postchecks
|
|
217
218
|
|
|
@@ -24,7 +24,7 @@ Load shared mechanics from [`../_shared/SKILL.md`](../_shared/SKILL.md).
|
|
|
24
24
|
| Command | Purpose | When |
|
|
25
25
|
| --- | --- | --- |
|
|
26
26
|
| `scip-query plan-context <target>` | Pre-edit planning context for a symbol, file, or module | Anchor each phase's step before delegating it. |
|
|
27
|
-
| `scip-query diff-gate --json` | Gate the current diff:
|
|
27
|
+
| `scip-query diff-gate --json` | Gate the current diff: architecture regressions plus echo, migration, coordination, doc-drift, unused-param, and new-dead candidates; exit 1 on blocking findings | Verify a handoff before accepting it and before closing the program. |
|
|
28
28
|
| `scip-query health --json` | Composite codebase health report with prioritized action list | Pre-register or check a program-level health benchmark. |
|
|
29
29
|
|
|
30
30
|
Use this shortlist first. Open [`../_shared/SKILL.md`](../_shared/SKILL.md) only when it is insufficient.
|
|
@@ -10,8 +10,16 @@ commands:
|
|
|
10
10
|
when: "Inventory evidence: files with overlapping dependency profiles."
|
|
11
11
|
- template: "scip-query cycles"
|
|
12
12
|
when: "Inventory evidence: circular dependency chains between files."
|
|
13
|
+
- template: "scip-query architecture --json"
|
|
14
|
+
when: "Measure configured boundaries, actual dependency traffic, forbidden edges, reciprocal pairs, and boundary cycles."
|
|
15
|
+
- template: "scip-query drift --architecture"
|
|
16
|
+
when: "Review direct drift findings together with boundary coverage and architecture signals."
|
|
13
17
|
- template: "scip-query co-change --json --full"
|
|
14
18
|
when: "Inventory evidence: hidden file-level coupling from git history."
|
|
19
|
+
- template: "scip-query health --write-baseline"
|
|
20
|
+
when: "Record reviewed existing debt before enabling architecture regression enforcement."
|
|
21
|
+
- template: "scip-query diff-gate"
|
|
22
|
+
when: "Verify that the current diff introduces no new declared architecture violation."
|
|
15
23
|
- template: "scip-query config-validate --json"
|
|
16
24
|
when: "Implement a slice: validate locality config after a move."
|
|
17
25
|
---
|
|
@@ -31,7 +39,11 @@ Load shared mechanics from [`../_shared/SKILL.md`](../_shared/SKILL.md).
|
|
|
31
39
|
| `scip-query locality-candidates --json --full` | Find directory-locality and ancestry candidates from consumer ownership | Inventory evidence: directory-locality candidates from consumer ownership. |
|
|
32
40
|
| `scip-query similar-files --full --json` | Find heuristic similar-file candidates from dependency profiles | Inventory evidence: files with overlapping dependency profiles. |
|
|
33
41
|
| `scip-query cycles` | Detect circular dependency chains between files | Inventory evidence: circular dependency chains between files. |
|
|
42
|
+
| `scip-query architecture --json` | Evaluate project-owned architectural boundaries and dependency rules | Measure configured boundaries, actual dependency traffic, forbidden edges, reciprocal pairs, and boundary cycles. |
|
|
43
|
+
| `scip-query drift --architecture` | Detect drift candidates: unused imports and declared architecture violations; pass --architecture for boundary context | Review direct drift findings together with boundary coverage and architecture signals. |
|
|
34
44
|
| `scip-query co-change --json --full` | Files that change together in git history without a dependency edge — hidden coupling candidates | Inventory evidence: hidden file-level coupling from git history. |
|
|
45
|
+
| `scip-query health --write-baseline` | Composite codebase health report with prioritized action list | Record reviewed existing debt before enabling architecture regression enforcement. |
|
|
46
|
+
| `scip-query diff-gate` | Gate the current diff: architecture regressions plus echo, migration, coordination, doc-drift, unused-param, and new-dead candidates; exit 1 on blocking findings | Verify that the current diff introduces no new declared architecture violation. |
|
|
35
47
|
| `scip-query config-validate --json` | Validate .scipquery.json, including structured suppressions and declared coupling groups | Implement a slice: validate locality config after a move. |
|
|
36
48
|
|
|
37
49
|
Use this shortlist first. Open [`../_shared/SKILL.md`](../_shared/SKILL.md) only when it is insufficient.
|
|
@@ -41,6 +53,16 @@ Use this shortlist first. Open [`../_shared/SKILL.md`](../_shared/SKILL.md) only
|
|
|
41
53
|
|
|
42
54
|
An ownership boundary is a folder, package, module, or convention that groups code around one stable responsibility.
|
|
43
55
|
|
|
56
|
+
A dependency edge points from code that relies on something to the code it relies on. For imports, `A -> B` means A imports B.
|
|
57
|
+
|
|
58
|
+
A forbidden edge is an actual cross-boundary dependency rejected by an explicit project rule. Directory distance or an unusual import does not make an edge forbidden by itself.
|
|
59
|
+
|
|
60
|
+
A layer is a responsibility ordered by dependency direction, such as presentation depending on application. A subsystem is a responsibility that owns an end-to-end capability, such as authentication or rendering. A package is a publication or build unit. A service is an independently running unit. Do not force all four into one layer hierarchy.
|
|
61
|
+
|
|
62
|
+
A reciprocal dependency is dependency traffic in both directions between two boundaries. It is a review signal because the boundaries exert mutual change pressure, not proof that either import is wrong.
|
|
63
|
+
|
|
64
|
+
An architecture ratchet is an enforcement rule that records existing violations while preventing new ones, allowing a large codebase to improve without a speculative rewrite.
|
|
65
|
+
|
|
44
66
|
A target structure is a proposed future layout that expresses an ownership model, not merely a prettier tree.
|
|
45
67
|
|
|
46
68
|
A migration slice is the smallest set of file moves and import updates that can be verified independently.
|
|
@@ -55,6 +77,8 @@ A slop codebase is a codebase whose files are arranged by accident, convenience,
|
|
|
55
77
|
4. Do not reward generic `shared` unless the shared concept has a name, owner, and cross-boundary consumers.
|
|
56
78
|
5. For messy repos, produce a discovery map and decisions instead of pretending the target is obvious.
|
|
57
79
|
6. Prefer small verified moves.
|
|
80
|
+
7. Configure descriptive boundaries before closing dependency rules.
|
|
81
|
+
8. Treat graph shape as evidence about responsibilities, never as a substitute for identifying them.
|
|
58
82
|
|
|
59
83
|
## Workflow
|
|
60
84
|
|
|
@@ -77,6 +101,8 @@ scip-query change-surface <file>
|
|
|
77
101
|
scip-query plan-context <file-or-symbol>
|
|
78
102
|
scip-query locality-candidates --json --full
|
|
79
103
|
scip-query cycles
|
|
104
|
+
scip-query architecture --json
|
|
105
|
+
scip-query drift --architecture
|
|
80
106
|
scip-query co-change
|
|
81
107
|
scip-query similar-files --min-similarity 0.6 --min-deps 3
|
|
82
108
|
scip-query similar-chains --min-similarity 0.5
|
|
@@ -98,7 +124,66 @@ Classify each candidate:
|
|
|
98
124
|
|
|
99
125
|
This step is complete only when mature, emerging, and accidental boundaries are separated.
|
|
100
126
|
|
|
101
|
-
### 4.
|
|
127
|
+
### 4. Build a descriptive architecture model
|
|
128
|
+
|
|
129
|
+
For a large existing codebase, identify real system units before calling them layers. Inventory:
|
|
130
|
+
|
|
131
|
+
- workspace packages and public exports;
|
|
132
|
+
- applications, services, and deployable entry points;
|
|
133
|
+
- domain capabilities and end-to-end subsystems;
|
|
134
|
+
- persistence, network, rendering, compiler, and other technical responsibilities;
|
|
135
|
+
- tests, routes, contracts, and ownership or architecture documentation;
|
|
136
|
+
- dependency and co-change evidence that shows which files already move as a unit.
|
|
137
|
+
|
|
138
|
+
Add mature boundary path patterns to `.scipquery.json` without `allowedDependencies` rows first:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"architecture": {
|
|
143
|
+
"boundaries": [
|
|
144
|
+
{ "name": "domain", "paths": ["src/domain/**"] },
|
|
145
|
+
{ "name": "runtime", "paths": ["src/runtime/**"] }
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Then run:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
scip-query config-validate --json
|
|
155
|
+
scip-query architecture --json
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Use unmapped and ambiguous files to repair boundary membership. Use actual boundary edges, reciprocal pairs, and strongly connected groups to test whether the names describe real separation.
|
|
159
|
+
|
|
160
|
+
This step is complete only when every configured boundary has a stated responsibility and the mapping gaps are understood.
|
|
161
|
+
|
|
162
|
+
### 5. Declare only supported dependency rules
|
|
163
|
+
|
|
164
|
+
An `allowedDependencies` row is closed: an outgoing target omitted from a present row is forbidden. A missing row makes no dependency claim.
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"architecture": {
|
|
169
|
+
"boundaries": [
|
|
170
|
+
{ "name": "domain", "paths": ["src/domain/**"] },
|
|
171
|
+
{ "name": "runtime", "paths": ["src/runtime/**"] }
|
|
172
|
+
],
|
|
173
|
+
"allowedDependencies": {
|
|
174
|
+
"domain": [],
|
|
175
|
+
"runtime": ["domain"]
|
|
176
|
+
},
|
|
177
|
+
"requireAcyclic": true
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
For each closed row, record the evidence for its intended direction. Do not copy the current dependency graph into the allow-list merely to obtain zero findings. Leave emerging or disputed rows undeclared.
|
|
183
|
+
|
|
184
|
+
This step is complete only when every forbidden edge is understood as either implementation debt, a false boundary, or a policy mistake.
|
|
185
|
+
|
|
186
|
+
### 6. Propose structure or decisions
|
|
102
187
|
|
|
103
188
|
Use this shape:
|
|
104
189
|
|
|
@@ -108,6 +193,10 @@ Use this shape:
|
|
|
108
193
|
## Scope
|
|
109
194
|
## Current Structure Map
|
|
110
195
|
## Boundary Maturity
|
|
196
|
+
## Descriptive Architecture Model
|
|
197
|
+
## Dependency Rules
|
|
198
|
+
## Forbidden-Edge Ledger
|
|
199
|
+
## Reciprocal and Cycle Review
|
|
111
200
|
## Target Structure
|
|
112
201
|
## Move Ledger
|
|
113
202
|
## Locality Config
|
|
@@ -120,7 +209,29 @@ List no-move decisions when broad consumers, route/package/contract surfaces, in
|
|
|
120
209
|
|
|
121
210
|
This step is complete only when every proposed move has a reason and verification path.
|
|
122
211
|
|
|
123
|
-
###
|
|
212
|
+
### 7. Ratchet, then implement one slice when asked
|
|
213
|
+
|
|
214
|
+
For a large repository with existing violations, review the direct findings and
|
|
215
|
+
write the shared health baseline:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
scip-query drift --architecture
|
|
219
|
+
scip-query health --write-baseline
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The baseline records stable architecture identities by boundary pair, not by
|
|
223
|
+
whichever example file happens to sort first. The default `scip-query
|
|
224
|
+
diff-gate` architecture check then compares only architecture identities; it
|
|
225
|
+
does not run every health detector. `diff-gate --baseline` remains the opt-in
|
|
226
|
+
full health ratchet and does not duplicate architecture findings.
|
|
227
|
+
|
|
228
|
+
Commit `.scipquery-baseline.json` with `.scipquery.json`. A missing baseline
|
|
229
|
+
causes the architecture gate to report that enforcement is not enabled; it
|
|
230
|
+
does not silently treat the current graph as accepted.
|
|
231
|
+
|
|
232
|
+
Prefer inspecting the least-broad edge inside a boundary cycle first, but
|
|
233
|
+
determine whether the repair is a move, dependency inversion, named shared
|
|
234
|
+
contract, boundary merge, or policy correction.
|
|
124
235
|
|
|
125
236
|
Before editing, state files to move, imports/exports/tests/docs to update, expected verification, and rollback risk. Then move the smallest high-confidence slice and run:
|
|
126
237
|
|
|
@@ -135,6 +246,9 @@ Also run project tests or typecheck for the affected workspace. If `.scipquery.j
|
|
|
135
246
|
```bash
|
|
136
247
|
scip-query config-validate
|
|
137
248
|
scip-query locality-candidates --json --full
|
|
249
|
+
scip-query architecture --json
|
|
250
|
+
scip-query drift --architecture
|
|
251
|
+
scip-query diff-gate
|
|
138
252
|
```
|
|
139
253
|
|
|
140
254
|
Then invoke `scip-verify`. The implementation is complete only when imports, tests, locality signals, and verification are checked.
|
|
@@ -12,8 +12,8 @@ commands:
|
|
|
12
12
|
when: "Map evidence: exports, consumers, and blast-radius risk."
|
|
13
13
|
- template: "scip-query affected <symbol>"
|
|
14
14
|
when: "Map evidence: transitive consumers of a candidate symbol."
|
|
15
|
-
- template: "scip-query drift --patterns"
|
|
16
|
-
when: "Map evidence:
|
|
15
|
+
- template: "scip-query drift --patterns --architecture"
|
|
16
|
+
when: "Map evidence: declared architecture violations plus boundary and pattern signals; treat opt-in pattern hits as leads, not findings."
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
# scip-maintainability
|
|
@@ -32,7 +32,7 @@ Load shared mechanics from [`../_shared/SKILL.md`](../_shared/SKILL.md).
|
|
|
32
32
|
| `scip-query surface <scope>` | What symbols consumers actually use from this module | Map evidence: what consumers actually use from the scope. |
|
|
33
33
|
| `scip-query change-surface <file>` | Pre-change briefing: exports, consumers, and blast-radius risk | Map evidence: exports, consumers, and blast-radius risk. |
|
|
34
34
|
| `scip-query affected <symbol>` | Transitive closure of symbols that could break if this symbol changes | Map evidence: transitive consumers of a candidate symbol. |
|
|
35
|
-
| `scip-query drift --patterns` | Detect
|
|
35
|
+
| `scip-query drift --patterns --architecture` | Detect drift candidates: unused imports and declared architecture violations; pass --architecture for boundary context | Map evidence: declared architecture violations plus boundary and pattern signals; treat opt-in pattern hits as leads, not findings. |
|
|
36
36
|
|
|
37
37
|
Use this shortlist first. Open [`../_shared/SKILL.md`](../_shared/SKILL.md) only when it is insufficient.
|
|
38
38
|
<!-- END GENERATED SKILL COMMANDS -->
|
|
@@ -23,7 +23,7 @@ Load shared mechanics from [`../_shared/SKILL.md`](../_shared/SKILL.md) when you
|
|
|
23
23
|
| --- | --- | --- |
|
|
24
24
|
| `scip-query status --capabilities` | Show index status for this project | Before routing: confirm the index is fresh. |
|
|
25
25
|
| `scip-query plan-context <target>` | Pre-edit planning context for a symbol, file, or module | Default loop: anchor a plan for the routed skill. |
|
|
26
|
-
| `scip-query diff-gate --json` | Gate the current diff:
|
|
26
|
+
| `scip-query diff-gate --json` | Gate the current diff: architecture regressions plus echo, migration, coordination, doc-drift, unused-param, and new-dead candidates; exit 1 on blocking findings | Default loop: the loop is complete only when this passes or is explained. |
|
|
27
27
|
|
|
28
28
|
Use this shortlist first. Open [`../_shared/SKILL.md`](../_shared/SKILL.md) only when it is insufficient.
|
|
29
29
|
<!-- END GENERATED SKILL COMMANDS -->
|
|
@@ -29,7 +29,7 @@ Load shared mechanics from [`../_shared/SKILL.md`](../_shared/SKILL.md).
|
|
|
29
29
|
| `scip-query duplicate-bodies --json --full` | Find exact duplicate small-body candidates across files | Cross-check: IDENTICAL groups are duplicate-bodies' job, not this skill's. |
|
|
30
30
|
| `scip-query code <symbol>` | Read the source code for a symbol (bounded to its definition range) | Classify a divergent group: read every member's body. |
|
|
31
31
|
| `scip-query refs <symbol>` | Find all files referencing a symbol | Pick the canonical twin: consumer count per member. |
|
|
32
|
-
| `scip-query diff-gate --json` | Gate the current diff:
|
|
32
|
+
| `scip-query diff-gate --json` | Gate the current diff: architecture regressions plus echo, migration, coordination, doc-drift, unused-param, and new-dead candidates; exit 1 on blocking findings | Verify: the twin-partner check must not flag a one-sided fix. |
|
|
33
33
|
|
|
34
34
|
Use this shortlist first. Open [`../_shared/SKILL.md`](../_shared/SKILL.md) only when it is insufficient.
|
|
35
35
|
<!-- END GENERATED SKILL COMMANDS -->
|
|
@@ -30,7 +30,7 @@ Load shared mechanics from [`../_shared/SKILL.md`](../_shared/SKILL.md).
|
|
|
30
30
|
| `scip-query doctor` | Diagnose config, index freshness, dependency readiness, and project capabilities | Prove the workspace: index freshness and dependency readiness. |
|
|
31
31
|
| `scip-query status --capabilities` | Show index status for this project | Prove the workspace: which evidence and verification capabilities are available. |
|
|
32
32
|
| `scip-query diff-impact --json` | Compute changed symbols and downstream consumers from current git diff | Assess the diff: changed symbols and downstream consumers. |
|
|
33
|
-
| `scip-query diff-gate --json` | Gate the current diff:
|
|
33
|
+
| `scip-query diff-gate --json` | Gate the current diff: architecture regressions plus echo, migration, coordination, doc-drift, unused-param, and new-dead candidates; exit 1 on blocking findings | Run the gate: the primary blocker for diff-specific risk. |
|
|
34
34
|
| `scip-query health --baseline` | Composite codebase health report with prioritized action list | Check health: compare findings against the committed baseline. |
|
|
35
35
|
| `scip-query doc-drift --json --full` | Stale-doc candidates: code the doc references or co-changed with kept changing after the doc stopped | Check docs: run when docs, AGENTS.md, or command surfaces changed. |
|
|
36
36
|
|
package/dist/chunk-2GX3TNOW.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import{b as le,c as O,d as T,e as H,k as be,l as ye}from"./chunk-OM6JHEW3.js";import{d as re,e as de,f as $,g as ue,l as fe,m as pe}from"./chunk-PZV2PGBR.js";import{D as me,n as ce,x as j}from"./chunk-4MFMTEJ4.js";import{a as te}from"./chunk-QEIGJJBC.js";import{d as ge,e as he}from"./chunk-MTDBHTSF.js";import{e as N,g as oe,s as ie,t as P,y as ae,z as se}from"./chunk-7XP7ZRSI.js";import{k as E,m as ee,p as ne}from"./chunk-JLZUM476.js";import{B as D,c as q}from"./chunk-TLTLJ4SW.js";import{a as Z}from"./chunk-64MNV6AB.js";import{c as z,d as Q,g as G,h as x,j as Y,l as K,q as X,s as _,y as F}from"./chunk-M2TRDR25.js";function Rn(e,n,t={}){let o=Me(e,[n],{additive:t.additive,semantic:t.semantic}),i=t.callableOnly?(o.get(n.symbolId)??[]).filter(s=>oe(s.symbol)||s.source==="ast-callsite"):o.get(n.symbolId)??[];return typeof t.limit=="number"?i.slice(0,t.limit):i}function Ce(e,n,t={}){return U(e,[n],t).get(n.symbolId)??[]}function U(e,n,t={}){let o=De(e)?Ee(e,n,{semantic:t.semantic!==!1}):ke(e);return typeof t.limit!="number"?new Map(n.map(i=>[i.symbolId,o.get(i.symbolId)??[]])):new Map(n.map(i=>[i.symbolId,(o.get(i.symbolId)??[]).slice(0,t.limit)]))}var Le=Q("caller-rows",{clearGroups:["whole-project"]}),_e=2e4;function De(e){return(e.get("SELECT COUNT(*) AS count FROM global_symbols")?.count??0)>_e}function ke(e){return Le.get(e,()=>{let n=P(e),t=Me(e,n),o=new Map;for(let a of n)o.set(a.symbol,a.symbolId);let i=new Map,s=new Map;for(let a of n){let r=t.get(a.symbolId);if(!(!r||r.length===0))for(let d of r){let c=o.get(d.symbol);if(c===void 0||c===a.symbolId)continue;let m=i.get(c);m||(m=[],i.set(c,m),s.set(c,new Set));let b=`${a.symbol}|${a.relativePath}`;s.get(c).has(b)||(s.get(c).add(b),m.push({symbol:a.symbol,file:a.relativePath,source:"caller-map-inversion"}))}}return i})}function Ee(e,n,t){let o=t.semantic?n.flatMap(r=>{let d=ve(e,r);return d?[d]:[]}):[],i=new Map(o.map(r=>[r.symbolId,r])),s=fe(e,o),a=new Map;for(let r of n){let d=[],c=new Set,m=p=>{if(p.symbol===r.symbol)return;let l=`${p.symbol}|${p.file}`;c.has(l)||(c.add(l),d.push(p))};for(let p of ye(e,r))p.file!==r.relativePath&&m({symbol:p.enclosingSymbol??p.file,file:p.file,source:"resolved-reference"});let b=i.get(r.symbolId);if(b)for(let p of s.get(b.symbolId)??[]){if(p.file===r.relativePath||e.isIgnored(p.file))continue;let l=se(ie(e,p.file),p.line);m({symbol:l?.symbol??p.file,file:p.file,source:"semantic-reference"})}a.set(r.symbolId,d)}return a}function ve(e,n){let t=ge().join(", "),o=he().join(", ");return e.get(`SELECT
|
|
2
|
-
d.id AS documentId,
|
|
3
|
-
gs.id AS symbolId,
|
|
4
|
-
gs.symbol,
|
|
5
|
-
d.relative_path AS relativePath,
|
|
6
|
-
COALESCE(der.start_line, c.start_line) AS startLine,
|
|
7
|
-
COALESCE(der.end_line, c.end_line) AS endLine,
|
|
8
|
-
COALESCE(gs.display_name, '') AS leaf,
|
|
9
|
-
NULL AS parentTypeName,
|
|
10
|
-
CASE WHEN gs.kind IN (${t}) OR gs.symbol LIKE '%().' THEN 1 ELSE 0 END AS isFunctionLike,
|
|
11
|
-
CASE WHEN gs.kind IN (${o}) THEN 1 ELSE 0 END AS isTypeLike,
|
|
12
|
-
gs.kind AS kind,
|
|
13
|
-
gs.documentation AS documentation,
|
|
14
|
-
gs.enclosing_symbol AS enclosingSymbol
|
|
15
|
-
FROM global_symbols gs
|
|
16
|
-
LEFT JOIN defn_enclosing_ranges der ON der.symbol_id = gs.id
|
|
17
|
-
LEFT JOIN chunks c ON c.document_id = der.document_id
|
|
18
|
-
JOIN documents d ON d.id = COALESCE(der.document_id, c.document_id)
|
|
19
|
-
WHERE gs.id = ?
|
|
20
|
-
LIMIT 1`,n.symbolId)??null}function Me(e,n,t={}){if(n.length===0)return new Map;let o=t.additive??!1,i=[],s=[];for(let m of n)D(m.relativePath)&&E(e,m.relativePath)!==null?i.push(m):s.push(m);let a=new Map,r=new Map,d=m=>{for(let[b,p]of m){let l=a.get(b);l||(l=[],a.set(b,l));let g=r.get(b);g||(g=new Set,r.set(b,g));for(let R of p){let C=`${R.symbol}|${R.chunkId}`;g.has(C)||(g.add(C),l.push(R))}}};i.length>0&&d(Te(e,i)),t.semantic!==!1&&d(Ke(Ae(e,n)));let c=o?n:s;return c.length>0&&d(Be(e,c)),a}function Ae(e,n){let t=X(),o=new Map,i=ue(e,n),s=[],a=[],r=0,d=0,c=0,m=0,b=0,p=0,l=0;for(let{definition:f,callees:u}of i.hits)b+=1,u.length>0&&(p+=1,l+=u.length,o.set(f.symbolId,u));let g=xe(e,i.hits);if(g.entries.length>0&&_("semantic.callees.prefetch-cache-write",()=>K(e,g.entries),()=>({entries:g.entries.length,sourceMissing:g.sourceMissing,skippedUnsupportedLanguage:g.skippedUnsupportedLanguage})),_("semantic.callees.cache-scan",()=>{for(let[f,u]of de(i.misses)){if(!j(f)){t&&(r+=u.length);continue}let h=F(e,f);if(!h){t&&(d+=u.length),a.push(...u);continue}let k=x(e,f,h),I=Re(e,f);if(!I){a.push(...u);continue}let B=Y(e,f,k,I);for(let y of u){let S=B.get(y.symbol)??null;if(S!==null){let w=Ne(S);if(w){t&&(c+=1),w.length>0&&o.set(y.symbolId,w);continue}t&&(m+=1)}s.push({def:y,contentHash:k,depsDigest:I})}}},()=>({definitions:n.length,skippedUnsupportedLanguage:r,sourceMissing:d,cacheHits:c,parseFailures:m,misses:s.length,unkeyed:a.length,inMemoryHits:b,inMemoryRows:p,inMemoryCalleeCount:l,resultRows:o.size})),s.length===0&&a.length===0)return o;let R=[...a,...s.map(f=>f.def)],C=0,v=_("semantic.callees.compute-misses",()=>{let f=pe(e,R);return C=f.size,f},()=>({definitions:R.length,misses:s.length,unkeyed:a.length,rows:C}));for(let[f,u]of v)o.set(f,u);let M=s.filter(f=>$(e).capability("semantic-callees",f.def.relativePath).available).map(f=>({relativePath:f.def.relativePath,symbol:f.def.symbol,contentHash:f.contentHash,depsDigest:f.depsDigest,payload:JSON.stringify(v.get(f.def.symbolId)??[])}));return M.length>0?_("semantic.callees.cache-write",()=>K(e,M),()=>({entries:M.length})):_("semantic.callees.cache-write-skip",()=>{},()=>({reason:"provider-unavailable",misses:s.length})),o}function xe(e,n){let t=[],o=new Map,i=0,s=0;for(let{definition:a,callees:r}of n){if(!j(a.relativePath)){s+=1;continue}if(!o.has(a.relativePath)){let c=F(e,a.relativePath),m=c?Re(e,a.relativePath):null;o.set(a.relativePath,c&&m?{contentHash:x(e,a.relativePath,c),depsDigest:m}:null)}let d=o.get(a.relativePath);if(!d){i+=1;continue}t.push({relativePath:a.relativePath,symbol:a.symbol,contentHash:d.contentHash,depsDigest:d.depsDigest,payload:JSON.stringify(r)})}return{entries:t,sourceMissing:i,skippedUnsupportedLanguage:s}}var Fe="typescript-callees-v1";function Re(e,n){let t=j(n);if(t==="typescript")return me(e,n,Fe)?.key??null;let o=Oe(e,n);return t==="rust"?G(JSON.stringify({kind:"semantic-callees",language:t,engine:ce(e.config.projectRoot),positionMapping:"nearby-leaf-v1",depsDigest:o})):o}function Ne(e){try{return JSON.parse(e)}catch{return null}}var Pe=z("semantic-deps-digest",{clearGroups:["whole-project","source-file"]});function Oe(e,n){return Pe.get(e,n,()=>{let o=[...te(e).get(n)??[]].sort().map(i=>`${i}:${x(e,i,F(e,i))}`);return G(o.join("|"))})}function Te(e,n){let t=new Map,o=He(n,t),i=H(e);for(let[s,a]of o){let r=E(e,s);if(!r)continue;let d=ae(a);for(let c of r){let m=d.get(c.line);if(!m)continue;let b=je(e,s,i,c);b&&b.symbol!==m.symbol&&t.get(m.symbolId).push({symbol:b.symbol,file:b.file,chunkId:c.line,source:"ast-callsite"})}}return t}function He(e,n){let t=new Map;for(let o of e){let i=t.get(o.relativePath);i?i.push(o):t.set(o.relativePath,[o]),n.set(o.symbolId,[])}for(let o of t.values())o.sort((i,s)=>i.endLine-i.startLine-(s.endLine-s.startLine));return t}function je(e,n,t,o){let i=O(n,t.get(o.calleeLeaf)??[]);if(i.length===0)return null;let s=$e(e,n,i,o.calleeQualifier);return s||T(e,n,i,o.memberAccess)}function $e(e,n,t,o){if(!o||D(n)!=="clojure")return null;let s=ne(e,n).filter(a=>a.kind==="namespace"&&a.localName===o&&a.sourcePath).map(a=>a.sourcePath);for(let a of s){let r=t.find(d=>q(a,d.file));if(r)return r}return t.find(a=>/`([^`]+)`\//.exec(a.symbol)?.[1]===o)??null}function Be(e,n){if(n.length===0)return new Map;let o=J(n.map(l=>l.documentId)).flatMap(l=>e.all(`SELECT c.document_id, c.id AS chunk_id, c.start_line, c.end_line, m.symbol_id
|
|
21
|
-
FROM mentions m
|
|
22
|
-
JOIN chunks c ON m.chunk_id = c.id
|
|
23
|
-
WHERE m.role != 1
|
|
24
|
-
AND c.document_id IN (${l.map(()=>"?").join(",")})`,...l)),i=new Map;for(let l of o)i.has(l.document_id)||i.set(l.document_id,[]),i.get(l.document_id).push(l);let a=J(o.map(l=>l.symbol_id)).flatMap(l=>e.all(`SELECT gs.id AS symbol_id, gs.symbol,
|
|
25
|
-
COALESCE(der.document_id, def_chunk.document_id) AS document_id
|
|
26
|
-
FROM global_symbols gs
|
|
27
|
-
LEFT JOIN defn_enclosing_ranges der ON der.symbol_id = gs.id
|
|
28
|
-
LEFT JOIN (
|
|
29
|
-
SELECT m.symbol_id, MIN(c.document_id) AS document_id
|
|
30
|
-
FROM mentions m
|
|
31
|
-
JOIN chunks c ON m.chunk_id = c.id
|
|
32
|
-
WHERE m.role = 1
|
|
33
|
-
AND m.symbol_id IN (${l.map(()=>"?").join(",")})
|
|
34
|
-
GROUP BY m.symbol_id
|
|
35
|
-
) def_chunk ON def_chunk.symbol_id = gs.id
|
|
36
|
-
WHERE gs.id IN (${l.map(()=>"?").join(",")})`,...l,...l)),r=J([...n.map(l=>l.documentId),...a.flatMap(l=>l.document_id===null?[]:[l.document_id])]),d=new Map(r.flatMap(l=>e.all(`SELECT id, relative_path FROM documents
|
|
37
|
-
WHERE id IN (${l.map(()=>"?").join(",")})`,...l).map(g=>[g.id,g.relative_path]))),c=new Map;for(let l of a)c.has(l.symbol_id)||c.set(l.symbol_id,{symbol:l.symbol,file:l.document_id!==null?d.get(l.document_id)??"":""});let m=new Map,b=d,p=Ge(n);for(let[l,g]of p){let C=[...i.get(l)??[]].sort((u,h)=>u.start_line-h.start_line||u.end_line-h.end_line),v=[...g].sort((u,h)=>u.startLine-h.startLine||u.endLine-h.endLine),M=new Set,f=0;for(let u of v){for(;f<C.length&&C[f].start_line<=u.endLine;)M.add(C[f]),f+=1;for(let y of M)y.end_line<u.startLine&&M.delete(y);let h=new Set,k=[],I=null,B=()=>{if(I)return I;let y=b.get(u.documentId)??"",S=new Set;if(y){let w=le(e,y),A=Math.max(0,u.startLine),V=Math.min(w.length-1,u.endLine);for(let L=A;L<=V;L+=1)for(let we of w[L])S.add(we)}return I=S,S};for(let y of M){if(y.symbol_id===u.symbolId)continue;let S=c.get(y.symbol_id);if(!S)continue;if(!(y.start_line>=u.startLine&&y.end_line<=u.endLine)){if(!(y.start_line<=u.endLine&&y.end_line>=u.startLine))continue;let L=N(S.symbol);if(!L||!B().has(L))continue}let A=`${S.symbol}|${y.chunk_id}`;h.has(A)||(h.add(A),k.push({...S,chunkId:y.chunk_id,source:"scip-chunk"}))}m.set(u.symbolId,k)}}return m}var Se=500;function J(e){let n=[...new Set(e)],t=[];for(let o=0;o<n.length;o+=Se)t.push(n.slice(o,o+Se));return t}function Ge(e){let n=new Map;for(let t of e){let o=n.get(t.documentId);o?o.push(t):n.set(t.documentId,[t])}return n}function Ke(e){let n=new Map;for(let[t,o]of e){let i=[];for(let s of o)i.push({symbol:s.symbol,file:s.file,chunkId:-1,source:"semantic-callee"});n.set(t,i)}return n}function Ie(e,n,t={}){let o=new Map;if(n&&n.length===0)return o;let i=Z(e,{includeIgnored:!1}),s=H(e),a=n??P(e),r=new Set(a.map(c=>c.symbolId)),d=Ye(a);if(Je(e,o,i,s,r,d),Ue(e,o,a,r),Qe(e,o,i,s,r,d),t.semantic!==!1){let c=$(e);qe(o,c.callerMap(Ze(a)))}return o}function Je(e,n,t,o,i,s){for(let a of t){if(!D(a))continue;let r=E(e,a);if(r)for(let d of r){if(s&&!s.has(d.calleeLeaf))continue;let c=O(a,o.get(d.calleeLeaf)??[]);if(!c||c.length===0)continue;let m=T(e,a,c,d.memberAccess);m&&i.has(m.symbolId)&&m.file!==a&&W(n,m.symbolId,a)}}}function Ue(e,n,t,o){let i=Ve(t);for(let s of We(e,o))e.isIgnored(s.relative_path)||ze(s,i.get(s.symbol_id))||W(n,s.symbol_id,s.relative_path)}function We(e,n){return re(e,n?[...n]:void 0)}function Ve(e){let n=new Map;for(let t of e)n.set(t.symbolId,{docId:t.documentId,startLine:t.startLine,endLine:t.endLine});return n}function ze(e,n){return!!n&&n.docId===e.document_id&&e.chunk_start>=n.startLine&&e.chunk_end<=n.endLine}function Qe(e,n,t,o,i,s){for(let a of t){if(D(a)!=="rust")continue;let r=ee(e,a,{includeRustAttributeNames:!0});if(r.length!==0)for(let{name:d}of r){if(s&&!s.has(d))continue;let c=o.get(d);if(c)for(let m of c)i.has(m.symbolId)&&m.file!==a&&W(n,m.symbolId,a)}}}function W(e,n,t){let o=e.get(n);o||(o=new Set,e.set(n,o)),o.add(t)}function Ye(e){let n=new Set;for(let t of e){let o="leaf"in t&&typeof t.leaf=="string"?t.leaf:"symbol"in t&&typeof t.symbol=="string"?N(t.symbol):"";o&&n.add(o)}return n.size>0?n:null}function Ze(e){return e.filter(n=>"relativePath"in n&&"symbol"in n&&"leaf"in n)}function qe(e,n){for(let[t,o]of n){let i=e.get(t);i||(i=new Set,e.set(t,i));for(let s of o)i.add(s)}}function Pn(e,n,t={}){return Ce(e,n,t)}function On(e,n,t={}){return U(e,n,t)}function Xe(e,n,t={}){return Ie(e,n,t)}function en(e,n,t={}){return be(e,n,t)}function Tn(e,n,t={}){let o=Xe(e,n,{semantic:t.semantic});return t.sourceFallback===!1?o:nn(o,en(e,n))}function nn(e,n){let t=new Map;for(let[o,i]of e)t.set(o,new Set(i));for(let[o,i]of n){let s=t.get(o)??new Set;for(let a of i)s.add(a);t.set(o,s)}return t}export{Rn as a,Me as b,Pn as c,On as d,Xe as e,en as f,Tn as g,nn as h};
|
|
38
|
-
//# sourceMappingURL=chunk-2GX3TNOW.js.map
|
package/dist/chunk-45XOH33S.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as C}from"./chunk-L2RE5P3X.js";import{m as v}from"./chunk-OM6JHEW3.js";import{f as O,i as x,m as T}from"./chunk-PZV2PGBR.js";import{d as A}from"./chunk-7XP7ZRSI.js";import{f as b}from"./chunk-JLZUM476.js";import{B as g}from"./chunk-TLTLJ4SW.js";function H(e,n={}){let{samples:o=50,scope:r,maxDisagreements:u=5}=n,l=new C(e),a=B(l.productionCallableDefinitions({scope:r,minLoc:2,requireFunctionLikeSymbol:!0}),o),c=K(e,a);if(a.length===0||!c)return{available:!1,sampleSize:a.length,oracleCoverage:0,scores:[],topDisagreements:[]};let t={references:P(),callees:P()},i=[],f=0,m=c==="semantic"?T(e,a):new Map,I=c==="source"?E(e,l,a):null;for(let s of a){let p=S(s,c==="semantic"?x(e,s).map(d=>d.file):[...I?.referencesBySymbolId.get(s.symbolId)??[]]),j=S(s,c==="semantic"?(m.get(s.symbolId)??[]).map(d=>d.file):[...I?.calleesBySymbolId.get(s.symbolId)??[]]);f+=1;let L=S(s,v(e,s).map(d=>d.file)),k=S(s,(l.calleeMap([s],{semantic:!1}).get(s.symbolId)??[]).map(d=>d.file)),w=y(c,"references"),R=y(c,"callees");Q(t.references,s,"references",L,p,w,i),Q(t.callees,s,"callees",k,j,R,i)}return i.sort((s,p)=>p.cheapOnly.length+p.oracleOnly.length-(s.cheapOnly.length+s.oracleOnly.length)),{available:!0,sampleSize:a.length,oracleCoverage:a.length>0?D(f/a.length):0,oracleKind:c,scores:["references","callees"].map(s=>F(s,t[s],c)),topDisagreements:i.slice(0,u)}}function P(){return{comparedSymbols:0,agreed:0,cheapTotal:0,oracleTotal:0,skippedOraclePartial:0}}function B(e,n){let o=[...e].sort((l,a)=>l.symbolId-a.symbolId);if(o.length<=n)return o;let r=o.length/n,u=[];for(let l=0;l<n;l++)u.push(o[Math.floor(l*r)]);return u}function K(e,n){let o=n[0];if(!o)return null;if(h(e,o))return"source";try{if(O(e).capability("semantic-references",o.relativePath).available)return"semantic"}catch{}return n.some(r=>h(e,r))?"source":null}function S(e,n){let o=new Set;for(let r of n)r!==e.relativePath&&o.add(r);return o}function Q(e,n,o,r,u,l,a){if(!l&&u.size===0){e.skippedOraclePartial+=1;return}e.comparedSymbols+=1,e.cheapTotal+=r.size,e.oracleTotal+=u.size;let c=[],t=[];for(let i of r)u.has(i)?e.agreed+=1:c.push(i);for(let i of u)r.has(i)||t.push(i);(c.length>0||t.length>0)&&a.push({symbol:A(n.symbol),question:o,cheapOnly:c,oracleOnly:t})}var z={references:!0,callees:!1};function F(e,n,o){let r=n.oracleTotal>0?n.agreed/n.oracleTotal:1,u=n.cheapTotal-n.agreed,l=y(o,e);return{question:e,comparedSymbols:n.comparedSymbols,precision:l&&n.cheapTotal>0?D(n.agreed/n.cheapTotal):null,recall:D(r),unverified:u,skippedOraclePartial:n.skippedOraclePartial}}function y(e,n){return e==="semantic"?z[n]:!1}function h(e,n){return g(n.relativePath)==="clojure"&&b(e,n.relativePath)!==null}function E(e,n,o){let r=new Map,u=new Map,l=o.filter(t=>h(e,t)),a=new Map;for(let t of l){let i=a.get(t.leaf)??[];i.push(t),a.set(t.leaf,i)}for(let t of n.sourceFiles()){if(g(t)!=="clojure")continue;let i=b(e,t);if(i)for(let f of i.fileIdentifiers)for(let m of a.get(f)??[])M(r,m.symbolId,t)}let c=new Map;for(let t of n.scopedDefinitions()){if(g(t.relativePath)!=="clojure")continue;let i=c.get(t.leaf)??[];i.push(t),c.set(t.leaf,i)}for(let t of l){let i=b(e,t.relativePath);if(i){for(let f of i.callSites)if(!(f.line<t.startLine||f.line>t.endLine))for(let m of c.get(f.calleeLeaf)??[])M(u,t.symbolId,m.relativePath)}}return{referencesBySymbolId:r,calleesBySymbolId:u}}function M(e,n,o){let r=e.get(n);if(r){r.add(o);return}e.set(n,new Set([o]))}function D(e){return Math.round(e*1e3)/1e3}export{H as a};
|
|
2
|
-
//# sourceMappingURL=chunk-45XOH33S.js.map
|