@duytransipher/gitnexus 1.4.6-sipher.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/LICENSE +73 -0
- package/README.md +261 -0
- package/dist/cli/ai-context.d.ts +23 -0
- package/dist/cli/ai-context.js +265 -0
- package/dist/cli/analyze.d.ts +12 -0
- package/dist/cli/analyze.js +345 -0
- package/dist/cli/augment.d.ts +13 -0
- package/dist/cli/augment.js +33 -0
- package/dist/cli/clean.d.ts +10 -0
- package/dist/cli/clean.js +60 -0
- package/dist/cli/eval-server.d.ts +37 -0
- package/dist/cli/eval-server.js +389 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +137 -0
- package/dist/cli/lazy-action.d.ts +6 -0
- package/dist/cli/lazy-action.js +18 -0
- package/dist/cli/list.d.ts +6 -0
- package/dist/cli/list.js +30 -0
- package/dist/cli/mcp.d.ts +8 -0
- package/dist/cli/mcp.js +36 -0
- package/dist/cli/serve.d.ts +4 -0
- package/dist/cli/serve.js +6 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +367 -0
- package/dist/cli/sipher-patched.d.ts +2 -0
- package/dist/cli/sipher-patched.js +77 -0
- package/dist/cli/skill-gen.d.ts +26 -0
- package/dist/cli/skill-gen.js +549 -0
- package/dist/cli/status.d.ts +6 -0
- package/dist/cli/status.js +36 -0
- package/dist/cli/tool.d.ts +60 -0
- package/dist/cli/tool.js +180 -0
- package/dist/cli/wiki.d.ts +15 -0
- package/dist/cli/wiki.js +365 -0
- package/dist/config/ignore-service.d.ts +26 -0
- package/dist/config/ignore-service.js +284 -0
- package/dist/config/supported-languages.d.ts +15 -0
- package/dist/config/supported-languages.js +16 -0
- package/dist/core/augmentation/engine.d.ts +26 -0
- package/dist/core/augmentation/engine.js +240 -0
- package/dist/core/embeddings/embedder.d.ts +60 -0
- package/dist/core/embeddings/embedder.js +251 -0
- package/dist/core/embeddings/embedding-pipeline.d.ts +51 -0
- package/dist/core/embeddings/embedding-pipeline.js +356 -0
- package/dist/core/embeddings/index.d.ts +9 -0
- package/dist/core/embeddings/index.js +9 -0
- package/dist/core/embeddings/text-generator.d.ts +24 -0
- package/dist/core/embeddings/text-generator.js +182 -0
- package/dist/core/embeddings/types.d.ts +87 -0
- package/dist/core/embeddings/types.js +32 -0
- package/dist/core/graph/graph.d.ts +2 -0
- package/dist/core/graph/graph.js +66 -0
- package/dist/core/graph/types.d.ts +66 -0
- package/dist/core/graph/types.js +1 -0
- package/dist/core/ingestion/ast-cache.d.ts +11 -0
- package/dist/core/ingestion/ast-cache.js +35 -0
- package/dist/core/ingestion/call-processor.d.ts +23 -0
- package/dist/core/ingestion/call-processor.js +793 -0
- package/dist/core/ingestion/call-routing.d.ts +68 -0
- package/dist/core/ingestion/call-routing.js +129 -0
- package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
- package/dist/core/ingestion/cluster-enricher.js +170 -0
- package/dist/core/ingestion/community-processor.d.ts +39 -0
- package/dist/core/ingestion/community-processor.js +312 -0
- package/dist/core/ingestion/constants.d.ts +16 -0
- package/dist/core/ingestion/constants.js +16 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +40 -0
- package/dist/core/ingestion/entry-point-scoring.js +353 -0
- package/dist/core/ingestion/export-detection.d.ts +18 -0
- package/dist/core/ingestion/export-detection.js +231 -0
- package/dist/core/ingestion/filesystem-walker.d.ts +28 -0
- package/dist/core/ingestion/filesystem-walker.js +81 -0
- package/dist/core/ingestion/framework-detection.d.ts +54 -0
- package/dist/core/ingestion/framework-detection.js +411 -0
- package/dist/core/ingestion/heritage-processor.d.ts +28 -0
- package/dist/core/ingestion/heritage-processor.js +251 -0
- package/dist/core/ingestion/import-processor.d.ts +34 -0
- package/dist/core/ingestion/import-processor.js +398 -0
- package/dist/core/ingestion/language-config.d.ts +46 -0
- package/dist/core/ingestion/language-config.js +167 -0
- package/dist/core/ingestion/mro-processor.d.ts +45 -0
- package/dist/core/ingestion/mro-processor.js +369 -0
- package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
- package/dist/core/ingestion/named-binding-extraction.js +363 -0
- package/dist/core/ingestion/parsing-processor.d.ts +19 -0
- package/dist/core/ingestion/parsing-processor.js +315 -0
- package/dist/core/ingestion/pipeline.d.ts +6 -0
- package/dist/core/ingestion/pipeline.js +401 -0
- package/dist/core/ingestion/process-processor.d.ts +51 -0
- package/dist/core/ingestion/process-processor.js +315 -0
- package/dist/core/ingestion/resolution-context.d.ts +53 -0
- package/dist/core/ingestion/resolution-context.js +132 -0
- package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
- package/dist/core/ingestion/resolvers/csharp.js +109 -0
- package/dist/core/ingestion/resolvers/go.d.ts +19 -0
- package/dist/core/ingestion/resolvers/go.js +42 -0
- package/dist/core/ingestion/resolvers/index.d.ts +18 -0
- package/dist/core/ingestion/resolvers/index.js +13 -0
- package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
- package/dist/core/ingestion/resolvers/jvm.js +87 -0
- package/dist/core/ingestion/resolvers/php.d.ts +15 -0
- package/dist/core/ingestion/resolvers/php.js +35 -0
- package/dist/core/ingestion/resolvers/python.d.ts +19 -0
- package/dist/core/ingestion/resolvers/python.js +52 -0
- package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
- package/dist/core/ingestion/resolvers/ruby.js +15 -0
- package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
- package/dist/core/ingestion/resolvers/rust.js +73 -0
- package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
- package/dist/core/ingestion/resolvers/standard.js +123 -0
- package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
- package/dist/core/ingestion/resolvers/utils.js +122 -0
- package/dist/core/ingestion/structure-processor.d.ts +2 -0
- package/dist/core/ingestion/structure-processor.js +36 -0
- package/dist/core/ingestion/symbol-table.d.ts +63 -0
- package/dist/core/ingestion/symbol-table.js +85 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +15 -0
- package/dist/core/ingestion/tree-sitter-queries.js +888 -0
- package/dist/core/ingestion/type-env.d.ts +49 -0
- package/dist/core/ingestion/type-env.js +613 -0
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +385 -0
- package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/csharp.js +383 -0
- package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/go.js +467 -0
- package/dist/core/ingestion/type-extractors/index.d.ts +22 -0
- package/dist/core/ingestion/type-extractors/index.js +31 -0
- package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
- package/dist/core/ingestion/type-extractors/jvm.js +681 -0
- package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/php.js +549 -0
- package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/python.js +455 -0
- package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/ruby.js +389 -0
- package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/rust.js +456 -0
- package/dist/core/ingestion/type-extractors/shared.d.ts +145 -0
- package/dist/core/ingestion/type-extractors/shared.js +810 -0
- package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/swift.js +137 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +127 -0
- package/dist/core/ingestion/type-extractors/types.js +1 -0
- package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/typescript.js +494 -0
- package/dist/core/ingestion/utils.d.ts +138 -0
- package/dist/core/ingestion/utils.js +1290 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +122 -0
- package/dist/core/ingestion/workers/parse-worker.js +1126 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +16 -0
- package/dist/core/ingestion/workers/worker-pool.js +128 -0
- package/dist/core/lbug/csv-generator.d.ts +33 -0
- package/dist/core/lbug/csv-generator.js +366 -0
- package/dist/core/lbug/lbug-adapter.d.ts +103 -0
- package/dist/core/lbug/lbug-adapter.js +769 -0
- package/dist/core/lbug/schema.d.ts +53 -0
- package/dist/core/lbug/schema.js +430 -0
- package/dist/core/search/bm25-index.d.ts +23 -0
- package/dist/core/search/bm25-index.js +96 -0
- package/dist/core/search/hybrid-search.d.ts +49 -0
- package/dist/core/search/hybrid-search.js +118 -0
- package/dist/core/tree-sitter/parser-loader.d.ts +5 -0
- package/dist/core/tree-sitter/parser-loader.js +63 -0
- package/dist/core/wiki/generator.d.ts +120 -0
- package/dist/core/wiki/generator.js +939 -0
- package/dist/core/wiki/graph-queries.d.ts +80 -0
- package/dist/core/wiki/graph-queries.js +238 -0
- package/dist/core/wiki/html-viewer.d.ts +10 -0
- package/dist/core/wiki/html-viewer.js +297 -0
- package/dist/core/wiki/llm-client.d.ts +43 -0
- package/dist/core/wiki/llm-client.js +186 -0
- package/dist/core/wiki/prompts.d.ts +53 -0
- package/dist/core/wiki/prompts.js +174 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +3 -0
- package/dist/mcp/compatible-stdio-transport.d.ts +25 -0
- package/dist/mcp/compatible-stdio-transport.js +200 -0
- package/dist/mcp/core/embedder.d.ts +27 -0
- package/dist/mcp/core/embedder.js +108 -0
- package/dist/mcp/core/lbug-adapter.d.ts +57 -0
- package/dist/mcp/core/lbug-adapter.js +455 -0
- package/dist/mcp/local/local-backend.d.ts +181 -0
- package/dist/mcp/local/local-backend.js +1722 -0
- package/dist/mcp/resources.d.ts +31 -0
- package/dist/mcp/resources.js +411 -0
- package/dist/mcp/server.d.ts +23 -0
- package/dist/mcp/server.js +296 -0
- package/dist/mcp/staleness.d.ts +15 -0
- package/dist/mcp/staleness.js +29 -0
- package/dist/mcp/tools.d.ts +24 -0
- package/dist/mcp/tools.js +292 -0
- package/dist/server/api.d.ts +10 -0
- package/dist/server/api.js +344 -0
- package/dist/server/mcp-http.d.ts +13 -0
- package/dist/server/mcp-http.js +100 -0
- package/dist/storage/git.d.ts +6 -0
- package/dist/storage/git.js +35 -0
- package/dist/storage/repo-manager.d.ts +138 -0
- package/dist/storage/repo-manager.js +299 -0
- package/dist/types/pipeline.d.ts +32 -0
- package/dist/types/pipeline.js +18 -0
- package/dist/unreal/bridge.d.ts +4 -0
- package/dist/unreal/bridge.js +113 -0
- package/dist/unreal/config.d.ts +6 -0
- package/dist/unreal/config.js +55 -0
- package/dist/unreal/types.d.ts +105 -0
- package/dist/unreal/types.js +1 -0
- package/hooks/claude/gitnexus-hook.cjs +238 -0
- package/hooks/claude/pre-tool-use.sh +79 -0
- package/hooks/claude/session-start.sh +42 -0
- package/package.json +100 -0
- package/scripts/ensure-cli-executable.cjs +21 -0
- package/scripts/patch-tree-sitter-swift.cjs +74 -0
- package/scripts/setup-unreal-gitnexus.ps1 +191 -0
- package/skills/gitnexus-cli.md +82 -0
- package/skills/gitnexus-debugging.md +89 -0
- package/skills/gitnexus-exploring.md +78 -0
- package/skills/gitnexus-guide.md +64 -0
- package/skills/gitnexus-impact-analysis.md +97 -0
- package/skills/gitnexus-pr-review.md +163 -0
- package/skills/gitnexus-refactoring.md +121 -0
- package/vendor/leiden/index.cjs +355 -0
- package/vendor/leiden/utils.cjs +392 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gitnexus-pr-review
|
|
3
|
+
description: "Use when the user wants to review a pull request, understand what a PR changes, assess risk of merging, or check for missing test coverage. Examples: \"Review this PR\", \"What does PR #42 change?\", \"Is this PR safe to merge?\""
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PR Review with GitNexus
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
- "Review this PR"
|
|
11
|
+
- "What does PR #42 change?"
|
|
12
|
+
- "Is this safe to merge?"
|
|
13
|
+
- "What's the blast radius of this PR?"
|
|
14
|
+
- "Are there missing tests for this PR?"
|
|
15
|
+
- Reviewing someone else's code changes before merge
|
|
16
|
+
|
|
17
|
+
## Workflow
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
1. gh pr diff <number> → Get the raw diff
|
|
21
|
+
2. gitnexus_detect_changes({scope: "compare", base_ref: "main"}) → Map diff to affected flows
|
|
22
|
+
3. For each changed symbol:
|
|
23
|
+
gitnexus_impact({target: "<symbol>", direction: "upstream"}) → Blast radius per change
|
|
24
|
+
4. gitnexus_context({name: "<key symbol>"}) → Understand callers/callees
|
|
25
|
+
5. READ gitnexus://repo/{name}/processes → Check affected execution flows
|
|
26
|
+
6. Summarize findings with risk assessment
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> If "Index is stale" → run `npx gitnexus analyze` in terminal before reviewing.
|
|
30
|
+
|
|
31
|
+
## Checklist
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
- [ ] Fetch PR diff (gh pr diff or git diff base...head)
|
|
35
|
+
- [ ] gitnexus_detect_changes to map changes to affected execution flows
|
|
36
|
+
- [ ] gitnexus_impact on each non-trivial changed symbol
|
|
37
|
+
- [ ] Review d=1 items (WILL BREAK) — are callers updated?
|
|
38
|
+
- [ ] gitnexus_context on key changed symbols to understand full picture
|
|
39
|
+
- [ ] Check if affected processes have test coverage
|
|
40
|
+
- [ ] Assess overall risk level
|
|
41
|
+
- [ ] Write review summary with findings
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Review Dimensions
|
|
45
|
+
|
|
46
|
+
| Dimension | How GitNexus Helps |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| **Correctness** | `context` shows callers — are they all compatible with the change? |
|
|
49
|
+
| **Blast radius** | `impact` shows d=1/d=2/d=3 dependents — anything missed? |
|
|
50
|
+
| **Completeness** | `detect_changes` shows all affected flows — are they all handled? |
|
|
51
|
+
| **Test coverage** | `impact({includeTests: true})` shows which tests touch changed code |
|
|
52
|
+
| **Breaking changes** | d=1 upstream items that aren't updated in the PR = potential breakage |
|
|
53
|
+
|
|
54
|
+
## Risk Assessment
|
|
55
|
+
|
|
56
|
+
| Signal | Risk |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| Changes touch <3 symbols, 0-1 processes | LOW |
|
|
59
|
+
| Changes touch 3-10 symbols, 2-5 processes | MEDIUM |
|
|
60
|
+
| Changes touch >10 symbols or many processes | HIGH |
|
|
61
|
+
| Changes touch auth, payments, or data integrity code | CRITICAL |
|
|
62
|
+
| d=1 callers exist outside the PR diff | Potential breakage — flag it |
|
|
63
|
+
|
|
64
|
+
## Tools
|
|
65
|
+
|
|
66
|
+
**gitnexus_detect_changes** — map PR diff to affected execution flows:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
gitnexus_detect_changes({scope: "compare", base_ref: "main"})
|
|
70
|
+
|
|
71
|
+
→ Changed: 8 symbols in 4 files
|
|
72
|
+
→ Affected processes: CheckoutFlow, RefundFlow, WebhookHandler
|
|
73
|
+
→ Risk: MEDIUM
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**gitnexus_impact** — blast radius per changed symbol:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
gitnexus_impact({target: "validatePayment", direction: "upstream"})
|
|
80
|
+
|
|
81
|
+
→ d=1 (WILL BREAK):
|
|
82
|
+
- processCheckout (src/checkout.ts:42) [CALLS, 100%]
|
|
83
|
+
- webhookHandler (src/webhooks.ts:15) [CALLS, 100%]
|
|
84
|
+
|
|
85
|
+
→ d=2 (LIKELY AFFECTED):
|
|
86
|
+
- checkoutRouter (src/routes/checkout.ts:22) [CALLS, 95%]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**gitnexus_impact with tests** — check test coverage:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
gitnexus_impact({target: "validatePayment", direction: "upstream", includeTests: true})
|
|
93
|
+
|
|
94
|
+
→ Tests that cover this symbol:
|
|
95
|
+
- validatePayment.test.ts [direct]
|
|
96
|
+
- checkout.integration.test.ts [via processCheckout]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**gitnexus_context** — understand a changed symbol's role:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
gitnexus_context({name: "validatePayment"})
|
|
103
|
+
|
|
104
|
+
→ Incoming calls: processCheckout, webhookHandler
|
|
105
|
+
→ Outgoing calls: verifyCard, fetchRates
|
|
106
|
+
→ Processes: CheckoutFlow (step 3/7), RefundFlow (step 1/5)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Example: "Review PR #42"
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
1. gh pr diff 42 > /tmp/pr42.diff
|
|
113
|
+
→ 4 files changed: payments.ts, checkout.ts, types.ts, utils.ts
|
|
114
|
+
|
|
115
|
+
2. gitnexus_detect_changes({scope: "compare", base_ref: "main"})
|
|
116
|
+
→ Changed symbols: validatePayment, PaymentInput, formatAmount
|
|
117
|
+
→ Affected processes: CheckoutFlow, RefundFlow
|
|
118
|
+
→ Risk: MEDIUM
|
|
119
|
+
|
|
120
|
+
3. gitnexus_impact({target: "validatePayment", direction: "upstream"})
|
|
121
|
+
→ d=1: processCheckout, webhookHandler (WILL BREAK)
|
|
122
|
+
→ webhookHandler is NOT in the PR diff — potential breakage!
|
|
123
|
+
|
|
124
|
+
4. gitnexus_impact({target: "PaymentInput", direction: "upstream"})
|
|
125
|
+
→ d=1: validatePayment (in PR), createPayment (NOT in PR)
|
|
126
|
+
→ createPayment uses the old PaymentInput shape — breaking change!
|
|
127
|
+
|
|
128
|
+
5. gitnexus_context({name: "formatAmount"})
|
|
129
|
+
→ Called by 12 functions — but change is backwards-compatible (added optional param)
|
|
130
|
+
|
|
131
|
+
6. Review summary:
|
|
132
|
+
- MEDIUM risk — 3 changed symbols affect 2 execution flows
|
|
133
|
+
- BUG: webhookHandler calls validatePayment but isn't updated for new signature
|
|
134
|
+
- BUG: createPayment depends on PaymentInput type which changed
|
|
135
|
+
- OK: formatAmount change is backwards-compatible
|
|
136
|
+
- Tests: checkout.test.ts covers processCheckout path, but no webhook test
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Review Output Format
|
|
140
|
+
|
|
141
|
+
Structure your review as:
|
|
142
|
+
|
|
143
|
+
```markdown
|
|
144
|
+
## PR Review: <title>
|
|
145
|
+
|
|
146
|
+
**Risk: LOW / MEDIUM / HIGH / CRITICAL**
|
|
147
|
+
|
|
148
|
+
### Changes Summary
|
|
149
|
+
- <N> symbols changed across <M> files
|
|
150
|
+
- <P> execution flows affected
|
|
151
|
+
|
|
152
|
+
### Findings
|
|
153
|
+
1. **[severity]** Description of finding
|
|
154
|
+
- Evidence from GitNexus tools
|
|
155
|
+
- Affected callers/flows
|
|
156
|
+
|
|
157
|
+
### Missing Coverage
|
|
158
|
+
- Callers not updated in PR: ...
|
|
159
|
+
- Untested flows: ...
|
|
160
|
+
|
|
161
|
+
### Recommendation
|
|
162
|
+
APPROVE / REQUEST CHANGES / NEEDS DISCUSSION
|
|
163
|
+
```
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gitnexus-refactoring
|
|
3
|
+
description: "Use when the user wants to rename, extract, split, move, or restructure code safely. Examples: \"Rename this function\", \"Extract this into a module\", \"Refactor this class\", \"Move this to a separate file\""
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Refactoring with GitNexus
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
- "Rename this function safely"
|
|
11
|
+
- "Extract this into a module"
|
|
12
|
+
- "Split this service"
|
|
13
|
+
- "Move this to a new file"
|
|
14
|
+
- Any task involving renaming, extracting, splitting, or restructuring code
|
|
15
|
+
|
|
16
|
+
## Workflow
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
1. gitnexus_impact({target: "X", direction: "upstream"}) → Map all dependents
|
|
20
|
+
2. gitnexus_query({query: "X"}) → Find execution flows involving X
|
|
21
|
+
3. gitnexus_context({name: "X"}) → See all incoming/outgoing refs
|
|
22
|
+
4. Plan update order: interfaces → implementations → callers → tests
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
> If "Index is stale" → run `npx gitnexus analyze` in terminal.
|
|
26
|
+
|
|
27
|
+
## Checklists
|
|
28
|
+
|
|
29
|
+
### Rename Symbol
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
- [ ] gitnexus_rename({symbol_name: "oldName", new_name: "newName", dry_run: true}) — preview all edits
|
|
33
|
+
- [ ] Review graph edits (high confidence) and ast_search edits (review carefully)
|
|
34
|
+
- [ ] If satisfied: gitnexus_rename({..., dry_run: false}) — apply edits
|
|
35
|
+
- [ ] gitnexus_detect_changes() — verify only expected files changed
|
|
36
|
+
- [ ] Run tests for affected processes
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Extract Module
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
- [ ] gitnexus_context({name: target}) — see all incoming/outgoing refs
|
|
43
|
+
- [ ] gitnexus_impact({target, direction: "upstream"}) — find all external callers
|
|
44
|
+
- [ ] Define new module interface
|
|
45
|
+
- [ ] Extract code, update imports
|
|
46
|
+
- [ ] gitnexus_detect_changes() — verify affected scope
|
|
47
|
+
- [ ] Run tests for affected processes
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Split Function/Service
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
- [ ] gitnexus_context({name: target}) — understand all callees
|
|
54
|
+
- [ ] Group callees by responsibility
|
|
55
|
+
- [ ] gitnexus_impact({target, direction: "upstream"}) — map callers to update
|
|
56
|
+
- [ ] Create new functions/services
|
|
57
|
+
- [ ] Update callers
|
|
58
|
+
- [ ] gitnexus_detect_changes() — verify affected scope
|
|
59
|
+
- [ ] Run tests for affected processes
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Tools
|
|
63
|
+
|
|
64
|
+
**gitnexus_rename** — automated multi-file rename:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
gitnexus_rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true})
|
|
68
|
+
→ 12 edits across 8 files
|
|
69
|
+
→ 10 graph edits (high confidence), 2 ast_search edits (review)
|
|
70
|
+
→ Changes: [{file_path, edits: [{line, old_text, new_text, confidence}]}]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**gitnexus_impact** — map all dependents first:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
gitnexus_impact({target: "validateUser", direction: "upstream"})
|
|
77
|
+
→ d=1: loginHandler, apiMiddleware, testUtils
|
|
78
|
+
→ Affected Processes: LoginFlow, TokenRefresh
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**gitnexus_detect_changes** — verify your changes after refactoring:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
gitnexus_detect_changes({scope: "all"})
|
|
85
|
+
→ Changed: 8 files, 12 symbols
|
|
86
|
+
→ Affected processes: LoginFlow, TokenRefresh
|
|
87
|
+
→ Risk: MEDIUM
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**gitnexus_cypher** — custom reference queries:
|
|
91
|
+
|
|
92
|
+
```cypher
|
|
93
|
+
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "validateUser"})
|
|
94
|
+
RETURN caller.name, caller.filePath ORDER BY caller.filePath
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Risk Rules
|
|
98
|
+
|
|
99
|
+
| Risk Factor | Mitigation |
|
|
100
|
+
| ------------------- | ----------------------------------------- |
|
|
101
|
+
| Many callers (>5) | Use gitnexus_rename for automated updates |
|
|
102
|
+
| Cross-area refs | Use detect_changes after to verify scope |
|
|
103
|
+
| String/dynamic refs | gitnexus_query to find them |
|
|
104
|
+
| External/public API | Version and deprecate properly |
|
|
105
|
+
|
|
106
|
+
## Example: Rename `validateUser` to `authenticateUser`
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
1. gitnexus_rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: true})
|
|
110
|
+
→ 12 edits: 10 graph (safe), 2 ast_search (review)
|
|
111
|
+
→ Files: validator.ts, login.ts, middleware.ts, config.json...
|
|
112
|
+
|
|
113
|
+
2. Review ast_search edits (config.json: dynamic reference!)
|
|
114
|
+
|
|
115
|
+
3. gitnexus_rename({symbol_name: "validateUser", new_name: "authenticateUser", dry_run: false})
|
|
116
|
+
→ Applied 12 edits across 8 files
|
|
117
|
+
|
|
118
|
+
4. gitnexus_detect_changes({scope: "all"})
|
|
119
|
+
→ Affected: LoginFlow, TokenRefresh
|
|
120
|
+
→ Risk: MEDIUM — run tests for these flows
|
|
121
|
+
```
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graphology Leiden Algorithm
|
|
3
|
+
* ============================
|
|
4
|
+
*
|
|
5
|
+
* JavaScript implementation of the Leiden community detection
|
|
6
|
+
* algorithm for graphology.
|
|
7
|
+
*
|
|
8
|
+
* Vendored from: https://github.com/graphology/graphology/tree/master/src/communities-leiden
|
|
9
|
+
* License: MIT
|
|
10
|
+
*
|
|
11
|
+
* [Reference]
|
|
12
|
+
* Traag, V. A., et al. "From Louvain to Leiden: Guaranteeing Well-Connected
|
|
13
|
+
* Communities". Scientific Reports, vol. 9, no 1, 2019, p. 5233.
|
|
14
|
+
* https://arxiv.org/abs/1810.08473
|
|
15
|
+
*/
|
|
16
|
+
var resolveDefaults = require('graphology-utils/defaults');
|
|
17
|
+
var isGraph = require('graphology-utils/is-graph');
|
|
18
|
+
var inferType = require('graphology-utils/infer-type');
|
|
19
|
+
var SparseMap = require('mnemonist/sparse-map');
|
|
20
|
+
var SparseQueueSet = require('mnemonist/sparse-queue-set');
|
|
21
|
+
var createRandomIndex = require('pandemonium/random-index').createRandomIndex;
|
|
22
|
+
var utils = require('./utils.cjs');
|
|
23
|
+
|
|
24
|
+
var indices = require('graphology-indices/louvain');
|
|
25
|
+
var addWeightToCommunity = utils.addWeightToCommunity;
|
|
26
|
+
|
|
27
|
+
var UndirectedLouvainIndex = indices.UndirectedLouvainIndex;
|
|
28
|
+
|
|
29
|
+
var UndirectedLeidenAddenda = utils.UndirectedLeidenAddenda;
|
|
30
|
+
|
|
31
|
+
var DEFAULTS = {
|
|
32
|
+
attributes: {
|
|
33
|
+
community: 'community',
|
|
34
|
+
weight: 'weight'
|
|
35
|
+
},
|
|
36
|
+
randomness: 0.01,
|
|
37
|
+
randomWalk: true,
|
|
38
|
+
resolution: 1,
|
|
39
|
+
rng: Math.random,
|
|
40
|
+
weighted: false
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
var EPSILON = 1e-10;
|
|
44
|
+
|
|
45
|
+
function tieBreaker(
|
|
46
|
+
bestCommunity,
|
|
47
|
+
currentCommunity,
|
|
48
|
+
targetCommunity,
|
|
49
|
+
delta,
|
|
50
|
+
bestDelta
|
|
51
|
+
) {
|
|
52
|
+
if (Math.abs(delta - bestDelta) < EPSILON) {
|
|
53
|
+
if (bestCommunity === currentCommunity) {
|
|
54
|
+
return false;
|
|
55
|
+
} else {
|
|
56
|
+
return targetCommunity > bestCommunity;
|
|
57
|
+
}
|
|
58
|
+
} else if (delta > bestDelta) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function undirectedLeiden(detailed, graph, options) {
|
|
66
|
+
var index = new UndirectedLouvainIndex(graph, {
|
|
67
|
+
attributes: {
|
|
68
|
+
weight: options.attributes.weight
|
|
69
|
+
},
|
|
70
|
+
keepDendrogram: detailed,
|
|
71
|
+
resolution: options.resolution,
|
|
72
|
+
weighted: options.weighted
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
var addenda = new UndirectedLeidenAddenda(index, {
|
|
76
|
+
randomness: options.randomness,
|
|
77
|
+
rng: options.rng
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
var randomIndex = createRandomIndex(options.rng);
|
|
81
|
+
|
|
82
|
+
// Communities
|
|
83
|
+
var currentCommunity, targetCommunity;
|
|
84
|
+
var communities = new SparseMap(Float64Array, index.C);
|
|
85
|
+
|
|
86
|
+
// Traversal
|
|
87
|
+
var queue = new SparseQueueSet(index.C),
|
|
88
|
+
start,
|
|
89
|
+
end,
|
|
90
|
+
weight,
|
|
91
|
+
ci,
|
|
92
|
+
ri,
|
|
93
|
+
s,
|
|
94
|
+
i,
|
|
95
|
+
j,
|
|
96
|
+
l;
|
|
97
|
+
|
|
98
|
+
// Metrics
|
|
99
|
+
var degree, targetCommunityDegree;
|
|
100
|
+
|
|
101
|
+
// Moves
|
|
102
|
+
var bestCommunity, bestDelta, deltaIsBetter, delta;
|
|
103
|
+
|
|
104
|
+
// Details
|
|
105
|
+
var deltaComputations = 0,
|
|
106
|
+
nodesVisited = 0,
|
|
107
|
+
moves = [],
|
|
108
|
+
currentMoves;
|
|
109
|
+
|
|
110
|
+
while (true) {
|
|
111
|
+
l = index.C;
|
|
112
|
+
|
|
113
|
+
currentMoves = 0;
|
|
114
|
+
|
|
115
|
+
// Traversal of the graph
|
|
116
|
+
ri = options.randomWalk ? randomIndex(l) : 0;
|
|
117
|
+
|
|
118
|
+
for (s = 0; s < l; s++, ri++) {
|
|
119
|
+
i = ri % l;
|
|
120
|
+
queue.enqueue(i);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
while (queue.size !== 0) {
|
|
124
|
+
i = queue.dequeue();
|
|
125
|
+
nodesVisited++;
|
|
126
|
+
|
|
127
|
+
degree = 0;
|
|
128
|
+
communities.clear();
|
|
129
|
+
|
|
130
|
+
currentCommunity = index.belongings[i];
|
|
131
|
+
|
|
132
|
+
start = index.starts[i];
|
|
133
|
+
end = index.starts[i + 1];
|
|
134
|
+
|
|
135
|
+
// Traversing neighbors
|
|
136
|
+
for (; start < end; start++) {
|
|
137
|
+
j = index.neighborhood[start];
|
|
138
|
+
weight = index.weights[start];
|
|
139
|
+
|
|
140
|
+
targetCommunity = index.belongings[j];
|
|
141
|
+
|
|
142
|
+
// Incrementing metrics
|
|
143
|
+
degree += weight;
|
|
144
|
+
addWeightToCommunity(communities, targetCommunity, weight);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Finding best community to move to
|
|
148
|
+
bestDelta = index.fastDeltaWithOwnCommunity(
|
|
149
|
+
i,
|
|
150
|
+
degree,
|
|
151
|
+
communities.get(currentCommunity) || 0,
|
|
152
|
+
currentCommunity
|
|
153
|
+
);
|
|
154
|
+
bestCommunity = currentCommunity;
|
|
155
|
+
|
|
156
|
+
for (ci = 0; ci < communities.size; ci++) {
|
|
157
|
+
targetCommunity = communities.dense[ci];
|
|
158
|
+
|
|
159
|
+
if (targetCommunity === currentCommunity) continue;
|
|
160
|
+
|
|
161
|
+
targetCommunityDegree = communities.vals[ci];
|
|
162
|
+
|
|
163
|
+
deltaComputations++;
|
|
164
|
+
|
|
165
|
+
delta = index.fastDelta(
|
|
166
|
+
i,
|
|
167
|
+
degree,
|
|
168
|
+
targetCommunityDegree,
|
|
169
|
+
targetCommunity
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
deltaIsBetter = tieBreaker(
|
|
173
|
+
bestCommunity,
|
|
174
|
+
currentCommunity,
|
|
175
|
+
targetCommunity,
|
|
176
|
+
delta,
|
|
177
|
+
bestDelta
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
if (deltaIsBetter) {
|
|
181
|
+
bestDelta = delta;
|
|
182
|
+
bestCommunity = targetCommunity;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (bestDelta < 0) {
|
|
187
|
+
bestCommunity = index.isolate(i, degree);
|
|
188
|
+
|
|
189
|
+
if (bestCommunity === currentCommunity) continue;
|
|
190
|
+
} else {
|
|
191
|
+
if (bestCommunity === currentCommunity) {
|
|
192
|
+
continue;
|
|
193
|
+
} else {
|
|
194
|
+
index.move(i, degree, bestCommunity);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
currentMoves++;
|
|
199
|
+
|
|
200
|
+
// Adding neighbors from other communities to the queue
|
|
201
|
+
start = index.starts[i];
|
|
202
|
+
end = index.starts[i + 1];
|
|
203
|
+
|
|
204
|
+
for (; start < end; start++) {
|
|
205
|
+
j = index.neighborhood[start];
|
|
206
|
+
targetCommunity = index.belongings[j];
|
|
207
|
+
|
|
208
|
+
if (targetCommunity !== bestCommunity) queue.enqueue(j);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
moves.push(currentMoves);
|
|
213
|
+
|
|
214
|
+
if (currentMoves === 0) {
|
|
215
|
+
index.zoomOut();
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!addenda.onlySingletons()) {
|
|
220
|
+
// We continue working on the induced graph
|
|
221
|
+
addenda.zoomOut();
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
var results = {
|
|
229
|
+
index: index,
|
|
230
|
+
deltaComputations: deltaComputations,
|
|
231
|
+
nodesVisited: nodesVisited,
|
|
232
|
+
moves: moves
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
return results;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Function returning the communities mapping of the graph.
|
|
240
|
+
*
|
|
241
|
+
* @param {boolean} assign - Assign communities to nodes attributes?
|
|
242
|
+
* @param {boolean} detailed - Whether to return detailed information.
|
|
243
|
+
* @param {Graph} graph - Target graph.
|
|
244
|
+
* @param {object} options - Options:
|
|
245
|
+
* @param {object} attributes - Attribute names:
|
|
246
|
+
* @param {string} community - Community node attribute name.
|
|
247
|
+
* @param {string} weight - Weight edge attribute name.
|
|
248
|
+
* @param {number} randomness - Randomness parameter.
|
|
249
|
+
* @param {boolean} randomWalk - Whether to traverse the graph in random order.
|
|
250
|
+
* @param {number} resolution - Resolution parameter.
|
|
251
|
+
* @param {function} rng - RNG function to use.
|
|
252
|
+
* @param {boolean} weighted - Whether to compute the weighted version.
|
|
253
|
+
* @return {object}
|
|
254
|
+
*/
|
|
255
|
+
function leiden(assign, detailed, graph, options) {
|
|
256
|
+
if (!isGraph(graph))
|
|
257
|
+
throw new Error(
|
|
258
|
+
'graphology-communities-leiden: the given graph is not a valid graphology instance.'
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
var type = inferType(graph);
|
|
262
|
+
|
|
263
|
+
if (type === 'mixed')
|
|
264
|
+
throw new Error(
|
|
265
|
+
'graphology-communities-leiden: cannot run the algorithm on a true mixed graph.'
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
if (type === 'directed')
|
|
269
|
+
throw new Error(
|
|
270
|
+
'graphology-communities-leiden: not yet implemented for directed graphs.'
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
// Attributes name
|
|
274
|
+
options = resolveDefaults(options, DEFAULTS);
|
|
275
|
+
|
|
276
|
+
// Empty graph case
|
|
277
|
+
var c = 0;
|
|
278
|
+
|
|
279
|
+
if (graph.size === 0) {
|
|
280
|
+
if (assign) {
|
|
281
|
+
graph.forEachNode(function (node) {
|
|
282
|
+
graph.setNodeAttribute(node, options.attributes.communities, c++);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
var communities = {};
|
|
289
|
+
|
|
290
|
+
graph.forEachNode(function (node) {
|
|
291
|
+
communities[node] = c++;
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
if (!detailed) return communities;
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
communities: communities,
|
|
298
|
+
count: graph.order,
|
|
299
|
+
deltaComputations: 0,
|
|
300
|
+
dendrogram: null,
|
|
301
|
+
level: 0,
|
|
302
|
+
modularity: NaN,
|
|
303
|
+
moves: null,
|
|
304
|
+
nodesVisited: 0,
|
|
305
|
+
resolution: options.resolution
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
var fn = undirectedLeiden;
|
|
310
|
+
|
|
311
|
+
var results = fn(detailed, graph, options);
|
|
312
|
+
|
|
313
|
+
var index = results.index;
|
|
314
|
+
|
|
315
|
+
// Standard output
|
|
316
|
+
if (!detailed) {
|
|
317
|
+
if (assign) {
|
|
318
|
+
index.assign(options.attributes.community);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return index.collect();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Detailed output
|
|
326
|
+
var output = {
|
|
327
|
+
count: index.C,
|
|
328
|
+
deltaComputations: results.deltaComputations,
|
|
329
|
+
dendrogram: index.dendrogram,
|
|
330
|
+
level: index.level,
|
|
331
|
+
modularity: index.modularity(),
|
|
332
|
+
moves: results.moves,
|
|
333
|
+
nodesVisited: results.nodesVisited,
|
|
334
|
+
resolution: options.resolution
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
if (assign) {
|
|
338
|
+
index.assign(options.attributes.community);
|
|
339
|
+
return output;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
output.communities = index.collect();
|
|
343
|
+
|
|
344
|
+
return output;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Exporting.
|
|
349
|
+
*/
|
|
350
|
+
var fn = leiden.bind(null, false, false);
|
|
351
|
+
fn.assign = leiden.bind(null, true, false);
|
|
352
|
+
fn.detailed = leiden.bind(null, false, true);
|
|
353
|
+
fn.defaults = DEFAULTS;
|
|
354
|
+
|
|
355
|
+
module.exports = fn;
|