skeletongraph 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. skeletongraph-0.1.0/.gitignore +132 -0
  2. skeletongraph-0.1.0/.skeletongraphignore +3 -0
  3. skeletongraph-0.1.0/LICENSE +21 -0
  4. skeletongraph-0.1.0/PKG-INFO +540 -0
  5. skeletongraph-0.1.0/README.md +462 -0
  6. skeletongraph-0.1.0/docs/ARM_FLOWS.md +223 -0
  7. skeletongraph-0.1.0/docs/EVAL_PLAN_FINAL.md +233 -0
  8. skeletongraph-0.1.0/docs/IMPLEMENTATION_PLAN.md +495 -0
  9. skeletongraph-0.1.0/docs/RESEARCH.md +346 -0
  10. skeletongraph-0.1.0/docs/RESEARCH_PLAN.md +269 -0
  11. skeletongraph-0.1.0/mcp.example.json +12 -0
  12. skeletongraph-0.1.0/pyproject.toml +113 -0
  13. skeletongraph-0.1.0/src/skeletongraph/__init__.py +35 -0
  14. skeletongraph-0.1.0/src/skeletongraph/__main__.py +6 -0
  15. skeletongraph-0.1.0/src/skeletongraph/assembly/__init__.py +0 -0
  16. skeletongraph-0.1.0/src/skeletongraph/assembly/constraint_store.py +301 -0
  17. skeletongraph-0.1.0/src/skeletongraph/assembly/context_routing.py +173 -0
  18. skeletongraph-0.1.0/src/skeletongraph/assembly/modifier.py +130 -0
  19. skeletongraph-0.1.0/src/skeletongraph/assembly/prompt_builder.py +791 -0
  20. skeletongraph-0.1.0/src/skeletongraph/build.py +704 -0
  21. skeletongraph-0.1.0/src/skeletongraph/cli/__init__.py +0 -0
  22. skeletongraph-0.1.0/src/skeletongraph/cli/init.py +350 -0
  23. skeletongraph-0.1.0/src/skeletongraph/cli/main.py +2050 -0
  24. skeletongraph-0.1.0/src/skeletongraph/cli/prepare.py +208 -0
  25. skeletongraph-0.1.0/src/skeletongraph/cli/run_exec.py +161 -0
  26. skeletongraph-0.1.0/src/skeletongraph/config.py +576 -0
  27. skeletongraph-0.1.0/src/skeletongraph/daemon.py +116 -0
  28. skeletongraph-0.1.0/src/skeletongraph/engine.py +740 -0
  29. skeletongraph-0.1.0/src/skeletongraph/eval/__init__.py +1 -0
  30. skeletongraph-0.1.0/src/skeletongraph/eval/token_counter.py +194 -0
  31. skeletongraph-0.1.0/src/skeletongraph/graph/__init__.py +0 -0
  32. skeletongraph-0.1.0/src/skeletongraph/graph/bloom.py +125 -0
  33. skeletongraph-0.1.0/src/skeletongraph/graph/bm25.py +136 -0
  34. skeletongraph-0.1.0/src/skeletongraph/graph/dependency.py +415 -0
  35. skeletongraph-0.1.0/src/skeletongraph/graph/embeddings.py +458 -0
  36. skeletongraph-0.1.0/src/skeletongraph/graph/inverted_index.py +403 -0
  37. skeletongraph-0.1.0/src/skeletongraph/graph/pagerank.py +131 -0
  38. skeletongraph-0.1.0/src/skeletongraph/hooks/__init__.py +1 -0
  39. skeletongraph-0.1.0/src/skeletongraph/hooks/claude_code.py +433 -0
  40. skeletongraph-0.1.0/src/skeletongraph/install/__init__.py +11 -0
  41. skeletongraph-0.1.0/src/skeletongraph/install/claude_code.py +310 -0
  42. skeletongraph-0.1.0/src/skeletongraph/install/cursor.py +173 -0
  43. skeletongraph-0.1.0/src/skeletongraph/install/detect.py +111 -0
  44. skeletongraph-0.1.0/src/skeletongraph/install/mcp_only.py +181 -0
  45. skeletongraph-0.1.0/src/skeletongraph/llm/__init__.py +0 -0
  46. skeletongraph-0.1.0/src/skeletongraph/llm/provider.py +138 -0
  47. skeletongraph-0.1.0/src/skeletongraph/llm/summarizer.py +208 -0
  48. skeletongraph-0.1.0/src/skeletongraph/parser/__init__.py +0 -0
  49. skeletongraph-0.1.0/src/skeletongraph/parser/ast_extractor.py +389 -0
  50. skeletongraph-0.1.0/src/skeletongraph/parser/edge_extractor.py +295 -0
  51. skeletongraph-0.1.0/src/skeletongraph/parser/import_resolver.py +268 -0
  52. skeletongraph-0.1.0/src/skeletongraph/parser/languages/__init__.py +0 -0
  53. skeletongraph-0.1.0/src/skeletongraph/parser/languages/cpp.py +250 -0
  54. skeletongraph-0.1.0/src/skeletongraph/parser/languages/csharp.py +201 -0
  55. skeletongraph-0.1.0/src/skeletongraph/parser/languages/go.py +265 -0
  56. skeletongraph-0.1.0/src/skeletongraph/parser/languages/java.py +215 -0
  57. skeletongraph-0.1.0/src/skeletongraph/parser/languages/php.py +192 -0
  58. skeletongraph-0.1.0/src/skeletongraph/parser/languages/python.py +548 -0
  59. skeletongraph-0.1.0/src/skeletongraph/parser/languages/ruby.py +173 -0
  60. skeletongraph-0.1.0/src/skeletongraph/parser/languages/rust.py +231 -0
  61. skeletongraph-0.1.0/src/skeletongraph/parser/languages/typescript.py +782 -0
  62. skeletongraph-0.1.0/src/skeletongraph/parser/node_kinds.py +114 -0
  63. skeletongraph-0.1.0/src/skeletongraph/parser/skeleton.py +364 -0
  64. skeletongraph-0.1.0/src/skeletongraph/retrieval/__init__.py +10 -0
  65. skeletongraph-0.1.0/src/skeletongraph/retrieval/bm25_flat.py +187 -0
  66. skeletongraph-0.1.0/src/skeletongraph/retrieval/budget.py +132 -0
  67. skeletongraph-0.1.0/src/skeletongraph/retrieval/classifier.py +554 -0
  68. skeletongraph-0.1.0/src/skeletongraph/retrieval/confidence.py +295 -0
  69. skeletongraph-0.1.0/src/skeletongraph/retrieval/dense.py +227 -0
  70. skeletongraph-0.1.0/src/skeletongraph/retrieval/detect_changes.py +229 -0
  71. skeletongraph-0.1.0/src/skeletongraph/retrieval/fusion.py +192 -0
  72. skeletongraph-0.1.0/src/skeletongraph/retrieval/intent.py +350 -0
  73. skeletongraph-0.1.0/src/skeletongraph/retrieval/model_router.py +109 -0
  74. skeletongraph-0.1.0/src/skeletongraph/retrieval/ranker.py +142 -0
  75. skeletongraph-0.1.0/src/skeletongraph/retrieval/resolver.py +913 -0
  76. skeletongraph-0.1.0/src/skeletongraph/retrieval/session.py +308 -0
  77. skeletongraph-0.1.0/src/skeletongraph/server/__init__.py +0 -0
  78. skeletongraph-0.1.0/src/skeletongraph/server/mcp.py +2223 -0
  79. skeletongraph-0.1.0/src/skeletongraph/session/__init__.py +1 -0
  80. skeletongraph-0.1.0/src/skeletongraph/session/decision_log.py +163 -0
  81. skeletongraph-0.1.0/src/skeletongraph/session/log.py +111 -0
  82. skeletongraph-0.1.0/src/skeletongraph/storage/__init__.py +0 -0
  83. skeletongraph-0.1.0/src/skeletongraph/storage/dirty.py +215 -0
  84. skeletongraph-0.1.0/src/skeletongraph/storage/local.py +312 -0
  85. skeletongraph-0.1.0/src/skeletongraph/storage/staleness.py +109 -0
  86. skeletongraph-0.1.0/src/skeletongraph/summary/__init__.py +49 -0
  87. skeletongraph-0.1.0/src/skeletongraph/summary/local.py +117 -0
  88. skeletongraph-0.1.0/src/skeletongraph/summary/ollama.py +264 -0
  89. skeletongraph-0.1.0/src/skeletongraph/summary/queue.py +356 -0
  90. skeletongraph-0.1.0/src/skeletongraph/summary/summary_store.py +116 -0
  91. skeletongraph-0.1.0/tests/conftest.py +0 -0
  92. skeletongraph-0.1.0/tests/fixtures/python_small/auth/__init__.py +1 -0
  93. skeletongraph-0.1.0/tests/fixtures/python_small/auth/exceptions.py +11 -0
  94. skeletongraph-0.1.0/tests/fixtures/python_small/auth/middleware.py +76 -0
  95. skeletongraph-0.1.0/tests/fixtures/python_small/auth/models.py +19 -0
  96. skeletongraph-0.1.0/tests/integration/test_pipeline.py +259 -0
  97. skeletongraph-0.1.0/tests/test_docstring_extraction.py +57 -0
  98. skeletongraph-0.1.0/tests/test_docstring_first.py +50 -0
  99. skeletongraph-0.1.0/tests/unit/test_ablations.py +202 -0
  100. skeletongraph-0.1.0/tests/unit/test_ast_parser.py +151 -0
  101. skeletongraph-0.1.0/tests/unit/test_bloom_index.py +169 -0
  102. skeletongraph-0.1.0/tests/unit/test_cli_run_exec.py +55 -0
  103. skeletongraph-0.1.0/tests/unit/test_config_cli_provider.py +50 -0
  104. skeletongraph-0.1.0/tests/unit/test_graph.py +216 -0
  105. skeletongraph-0.1.0/tests/unit/test_model_router.py +53 -0
  106. skeletongraph-0.1.0/tests/unit/test_sg_chain_arm.py +71 -0
  107. skeletongraph-0.1.0/tests/unit/test_skeleton.py +205 -0
@@ -0,0 +1,132 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg-info/
7
+ dist/
8
+ build/
9
+ *.egg
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # IDE — machine-local files only, not for the public repo
17
+ .claude/
18
+ .cursor/
19
+ .vscode/
20
+ .idea/
21
+ *.swp
22
+ *.swo
23
+
24
+ # Agent-specific guidance files (local to whichever IDE you use)
25
+ AGENT_RULES.md
26
+ CLAUDE.md
27
+ CURSOR_SETUP.md
28
+ GEMINI_DIAGRAM_PROMPT.md
29
+ CURATOR.md
30
+
31
+ # SkeletonGraph index (generated, not committed)
32
+ .skeletongraph/
33
+ **/ .skeletongraph/
34
+
35
+ # Environment
36
+ .env
37
+ .env.local
38
+
39
+ # Machine-local MCP config (copy mcp.example.json and fill in your paths)
40
+ mcp.json
41
+
42
+ # OS
43
+ .DS_Store
44
+ Thumbs.db
45
+
46
+ # Testing
47
+ .coverage
48
+ htmlcov/
49
+ .pytest_cache/
50
+
51
+ # Eval scratch — generated, not committed (scripts ARE committed)
52
+ benchmarks/repos/
53
+ eval/datasets/repos/
54
+ eval/datasets/_repo_cache/
55
+ eval/datasets/_agent_work/
56
+ # Per-task editable checkouts made for the Claude Code arms — one full repo copy
57
+ # PER TASK PER ARM (gigabytes). Never committable; `git add -A` would otherwise
58
+ # try to stage every cloned repository in the benchmark.
59
+ eval/datasets/_claude_repos/
60
+ eval/datasets/*.jsonl
61
+ eval/results/
62
+ eval/figures/
63
+ eval/logs/
64
+
65
+ # Internal planning docs (not public)
66
+ docs/plan.md
67
+ docs/sg.md
68
+ docs/BLUEPRINT.md
69
+ docs/CODEMEMBENCH.md
70
+ docs/results_memory_analysis.md
71
+ docs/*.local.md
72
+ EVALUATION_WORKFLOW.md
73
+ evaluation_dataset.md
74
+ SWE_BENCH_WORKFLOW.md
75
+
76
+ test_mcp_tools.py
77
+
78
+ # Local scratch and one-off migration helpers
79
+ scratch_*.py
80
+ scratch_select.py
81
+ eval/scripts/patch_setup.py
82
+
83
+ architecture.md
84
+ decisions.md
85
+ project.md
86
+ constraints
87
+
88
+ # Scratch eval runbooks — working docs, not part of the package
89
+ temp/
90
+
91
+ .venv-aider/
92
+ eval/results/agent_*/
93
+ **/.hybrid_index/
94
+ **/.skeletongraph/
95
+
96
+ eval/curator/*.pkl
97
+ eval/results_backup.zip
98
+
99
+ # SWE-bench harness output JSONs (run_harness() writes <arm>.<run_tag>.json to CWD)
100
+ bm25.*.json
101
+ grep.*.json
102
+ hybrid.*.json
103
+ none.*.json
104
+ sg.*.json
105
+ sg-*.json
106
+ cbmem.*.json
107
+ aider.*.json
108
+ graphify.*.json
109
+ fusion.*.json
110
+ native.*.json
111
+ summary-*.json
112
+ logs/
113
+
114
+ # External benchmark clone (huge, has its own .git + submodules: mini-swe-agent,
115
+ # SWE-agent). Cloned per machine; never part of this repo.
116
+ SWE-bench_Pro-os/
117
+
118
+ # graphify extract output (per-repo graph; never commit, never let it leak into a patch)
119
+ graphify-out/
120
+
121
+ # LaTeX build byproducts (regenerated by pdflatex/bibtex; never source)
122
+ docs/paper/*.aux
123
+ docs/paper/*.log
124
+ docs/paper/*.out
125
+ docs/paper/*.bbl
126
+ docs/paper/*.blg
127
+ **/graphify-out/
128
+
129
+ eval/scripts/set_nim_env.bat
130
+ eval/scripts/set_nim_env.ps1
131
+
132
+ .aider.tags.cache.v4
@@ -0,0 +1,3 @@
1
+ # SkeletonGraph local index
2
+ .skeletongraph/session/
3
+ .skeletongraph/*.tmp
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yash Doke
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,540 @@
1
+ Metadata-Version: 2.4
2
+ Name: skeletongraph
3
+ Version: 0.1.0
4
+ Summary: Token-minimal, constraint-preserving context assembly for AI coding agents
5
+ Project-URL: Homepage, https://github.com/yashdoke7/skeletongraph
6
+ Project-URL: Documentation, https://github.com/yashdoke7/skeletongraph/tree/main/docs
7
+ Project-URL: Repository, https://github.com/yashdoke7/skeletongraph
8
+ Author-email: Yash Doke <yashdoke215@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: ast,claude-code,coding-agent,context,graph,llm,mcp,skeleton,token-optimization,tree-sitter
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Software Development :: Code Generators
23
+ Classifier: Topic :: Software Development :: Libraries
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: click>=8.0
26
+ Requires-Dist: huggingface-hub<0.30,>=0.20
27
+ Requires-Dist: mmh3>=4.0
28
+ Requires-Dist: numpy>=1.24
29
+ Requires-Dist: rich>=13.0
30
+ Requires-Dist: sentence-transformers<4,>=3.0
31
+ Requires-Dist: tiktoken>=0.7.0
32
+ Requires-Dist: tree-sitter-c-sharp>=0.23
33
+ Requires-Dist: tree-sitter-cpp>=0.23
34
+ Requires-Dist: tree-sitter-go>=0.23
35
+ Requires-Dist: tree-sitter-java>=0.23
36
+ Requires-Dist: tree-sitter-javascript>=0.23
37
+ Requires-Dist: tree-sitter-php>=0.23
38
+ Requires-Dist: tree-sitter-python>=0.23
39
+ Requires-Dist: tree-sitter-ruby>=0.23
40
+ Requires-Dist: tree-sitter-rust>=0.23
41
+ Requires-Dist: tree-sitter-typescript>=0.23
42
+ Requires-Dist: tree-sitter>=0.23
43
+ Provides-Extra: all
44
+ Requires-Dist: datasets<3; extra == 'all'
45
+ Requires-Dist: litellm>=1.0; extra == 'all'
46
+ Requires-Dist: matplotlib; extra == 'all'
47
+ Requires-Dist: mcp>=1.0; extra == 'all'
48
+ Requires-Dist: openai; extra == 'all'
49
+ Requires-Dist: pandas; extra == 'all'
50
+ Requires-Dist: pytest; extra == 'all'
51
+ Requires-Dist: pytest-cov; extra == 'all'
52
+ Requires-Dist: ruff; extra == 'all'
53
+ Requires-Dist: seaborn; extra == 'all'
54
+ Requires-Dist: swebench; extra == 'all'
55
+ Requires-Dist: watchdog>=3.0; extra == 'all'
56
+ Provides-Extra: daemon
57
+ Requires-Dist: watchdog>=3.0; extra == 'daemon'
58
+ Provides-Extra: dev
59
+ Requires-Dist: pytest; extra == 'dev'
60
+ Requires-Dist: pytest-cov; extra == 'dev'
61
+ Requires-Dist: ruff; extra == 'dev'
62
+ Provides-Extra: embeddings
63
+ Provides-Extra: eval
64
+ Requires-Dist: datasets<3; extra == 'eval'
65
+ Requires-Dist: matplotlib; extra == 'eval'
66
+ Requires-Dist: openai; extra == 'eval'
67
+ Requires-Dist: pandas; extra == 'eval'
68
+ Requires-Dist: seaborn; extra == 'eval'
69
+ Requires-Dist: swebench; extra == 'eval'
70
+ Provides-Extra: eval-strong
71
+ Requires-Dist: aider-chat>=0.82; extra == 'eval-strong'
72
+ Requires-Dist: rank-bm25>=0.2; extra == 'eval-strong'
73
+ Provides-Extra: llm
74
+ Requires-Dist: litellm>=1.0; extra == 'llm'
75
+ Provides-Extra: mcp
76
+ Requires-Dist: mcp>=1.0; extra == 'mcp'
77
+ Description-Content-Type: text/markdown
78
+
79
+ # SkeletonGraph
80
+
81
+ <p align="center">
82
+ <a href="https://pypi.org/project/skeletongraph/"><img src="https://img.shields.io/pypi/v/skeletongraph.svg?color=blue" alt="PyPI"></a>
83
+ <a href="https://pypi.org/project/skeletongraph/"><img src="https://img.shields.io/pypi/pyversions/skeletongraph.svg" alt="Python versions"></a>
84
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="MIT License"></a>
85
+ <a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-server-orange.svg" alt="MCP server"></a>
86
+ </p>
87
+
88
+ **Coding agents burn tokens reading whole files to find one function. SkeletonGraph
89
+ indexes your repo with tree-sitter — no LLM — and hands the agent the exact function
90
+ to edit, over MCP.**
91
+
92
+ <p align="center">
93
+ <img src="docs/paper/figures/skeletongraph_hero.gif"
94
+ alt="How SkeletonGraph works: index a repo with tree-sitter (no LLM), fuse lexical + semantic + structural retrieval, and return the one function to edit over MCP"
95
+ width="100%">
96
+ </p>
97
+
98
+ <p align="center"><em>Index once (no LLM) → fuse lexical + semantic + structural signals → return the exact function, served to your agent over MCP.</em></p>
99
+
100
+ SkeletonGraph (SG) indexes a codebase into function-level structure, a cross-file
101
+ call graph, and PageRank centrality — **with no LLM**. At query time it resolves the
102
+ symbols an issue names, expands the call graph, and reranks a BM25 recall pool so the
103
+ agent lands the **right function** instead of burning turns reading files. Its
104
+ companion operating point, **`sg-rerank`** (the product default), takes BM25's wide
105
+ recall pool and reorders it by structural confirmation — best file *and* function
106
+ recall of any method we tested, at the lowest token cost.
107
+
108
+ The thesis: code-context tools have been validated as a **token-optimization** game
109
+ (token-count math). We re-center on **retrieval quality** — landing the correct
110
+ function — of which lower token cost is a *consequence*, visible only end-to-end
111
+ inside the agent loop.
112
+
113
+ ## Results
114
+
115
+ All numbers below are regenerated from the released run artifacts
116
+ (`python -m eval.scripts.make_paper_figures`). The full verified ledger, including
117
+ withdrawn claims, is in [`docs/paper/FINDINGS.md`](docs/paper/FINDINGS.md).
118
+
119
+ ### 1. Controlled retrieval ablation (react loop, open-weight model, 100 tasks)
120
+
121
+ Identical action space for every arm; **only the retrieval backend changes**. The
122
+ `none` arm gets no code access at all and establishes the memorization floor.
123
+
124
+ | arm | pass@1 | file recall@1 | function hit | tokens (k) | turns | $/task |
125
+ |---|--:|--:|--:|--:|--:|--:|
126
+ | **`sg-fusion`** | **42.0%** | .737 | **57%** | **180** | 21.9 | **.052** |
127
+ | `bm25` | 41.0% | .642 | 43% | 264 | 24.6 | .074 |
128
+ | `graphify` (knowledge graph) | 41.0% | .223 | 9% | 275 | 25.6 | .078 |
129
+ | `grep` | 39.0% | .647 | 0% | 282 | 22.4 | .079 |
130
+ | `aider` (repo-map) | 36.7% | — | — | 1,126 | 18.1 | .160 |
131
+ | `none` (no retrieval) | 35.0% | — | — | 345 | 23.6 | .066 |
132
+
133
+ **`sg-fusion` is the top arm, the cheapest arm, and the only one that localizes to
134
+ the function** (57% vs grep's 0% — lexical search is file-granular by construction).
135
+ Against the closed-book floor of 35.0%, retrieval is worth **+7 points** here.
136
+
137
+ `sg-rerank`'s recall/cost profile is reported separately in the agent-free intrinsic
138
+ retrieval ablation in [`docs/paper/skeletongraph.tex`](docs/paper/skeletongraph.tex)
139
+ (Table 2, §5.1) — best MRR/recall@10 short of full fusion, at the lowest index cost.
140
+
141
+ ### 2. Deployment: SkeletonGraph vs native Claude Code (MCP, Docker-verified)
142
+
143
+ The product itself — SG as an MCP server driving **Claude Code (sonnet)** against
144
+ Claude Code on its own tools. 100 paired SWE-bench Verified tasks:
145
+
146
+ | arm | pass@1 | file recall@1 | turns | $/task |
147
+ |---|--:|--:|--:|--:|
148
+ | `native` (Claude's own Grep/Read) | 74/100 | .663 | 14.5 | .434 |
149
+ | **`sg-fusion`** (SkeletonGraph MCP) | 75/100 | **.836** | **11.4** | **.371** |
150
+
151
+ **Equivalent solve rate at −14.6% cost and −21.4% turns.** The saving is not spread
152
+ evenly — it lives almost entirely in the tail:
153
+
154
+ | cost percentile | native | +SG | change |
155
+ |---|--:|--:|--:|
156
+ | 50th (median task) | $0.255 | $0.260 | **+1.9%** |
157
+ | 90th | $1.010 | $0.752 | −25.6% |
158
+ | 95th (worst tasks) | $1.559 | $0.896 | **−42.5%** |
159
+
160
+ Retrieval does nothing for the typical task and removes over 40% of the cost of the
161
+ worst ones. Paired bootstrap 95% CI on the mean: [−25.3%, −1.2%]; McNemar on pass@1:
162
+ p = 1.0 (no difference).
163
+
164
+ ### 3. The ceiling: what structural retrieval cannot do
165
+
166
+ ![Retrieval collapses as location cues are removed](docs/paper/figures/fig_ceiling.png)
167
+
168
+ `sg-fusion` runs all three non-LLM retrieval paradigms at once — lexical (BM25),
169
+ semantic (code embeddings), and topological (call graph). Crossing *memorization*
170
+ (standard vs. decontaminated benchmark) against *location cues* (original vs.
171
+ prose-stripped issue text) shows the limit:
172
+
173
+ | condition | cost | file recall native → SG |
174
+ |---|--:|--:|
175
+ | SWE-Verified, raw | −32.2% | .661 → .861 |
176
+ | SWE-Verified, **prose-only** | −21.1% | .717 → .711 (**no edge**) |
177
+ | SWE-rebench (unseen repos), raw | −26.4% | .500 → .639 |
178
+ | SWE-rebench, **prose-only** | −31.3% | .394 → .439 |
179
+
180
+ Two things happen at once. **The retrieval advantage collapses** — on prose-only
181
+ issues it disappears entirely — and the lexical baseline falls in parallel, so this
182
+ is a property of the whole category, not of one implementation. **Yet the cost saving
183
+ persists in every condition**, including the one where retrieval quality is identical
184
+ to the baseline. Retrieval quality is therefore *not* the mechanism producing the
185
+ saving; bounding how far the agent wanders before it commits is.
186
+
187
+ > SWE-Verified rows are restricted to the same 15 tasks as the prose run so raw and
188
+ > prose are paired. That subset is *not* representative of the full 100 (SG saves
189
+ > −32.2% on it vs −14.6% overall) — do not compare it against the n=100 figure.
190
+
191
+ ### 4. Deployment finding: slow MCP servers are structurally excluded
192
+
193
+ Two graph/LSP-based competitors wired as MCP servers **never participated at all**.
194
+ Claude Code's headless (`-p`) mode finalizes its tool manifest within ~2 seconds of
195
+ launch and never updates it; servers needing real bootstrap time (a language server,
196
+ a Node CLI + index) finish their handshake just past that window and are silently
197
+ absent for the entire run — confirmed via session-init transcripts and each server's
198
+ own logs showing it was ready seconds later.
199
+
200
+ This is a **deployment-mode result, not a retrieval-quality one**, and we report no
201
+ performance comparison for those systems: with zero tool calls, any such number would
202
+ measure their absence rather than their retrieval. A separately wired zero-LLM graph
203
+ competitor connected cleanly with all 14 tools visible, yet the agent never invoked
204
+ one across 10 tasks, defaulting to native `grep` every time. Fast connection and
205
+ actual adoption are prerequisites that retrieval quality cannot substitute for.
206
+
207
+ SkeletonGraph is wrapper-first: it returns a full context packet or exposes a
208
+ retrieval index (AST skeletons + call graph + local summaries + optional embeddings)
209
+ so the IDE agent or CLI can choose targets.
210
+
211
+ SkeletonGraph has two product surfaces:
212
+
213
+ - **SG IDE**: MCP context server for Cursor, Claude Code, Copilot, Codex,
214
+ Antigravity, Windsurf, and other agentic IDEs.
215
+ - **SG CLI**: terminal pipeline for route, prepare, dry-run, provider execution,
216
+ and cost-aware model selection.
217
+
218
+ ## Why SkeletonGraph
219
+
220
+ Most coding agents spend expensive turns discovering the repo:
221
+
222
+ ```text
223
+ search -> read file -> read neighbor -> read tests -> realize the target
224
+ ```
225
+
226
+ SkeletonGraph moves that work into a deterministic graph pipeline:
227
+
228
+ ```text
229
+ prompt -> (optional) retrieval planner -> classify task -> find target nodes -> expand graph -> assemble packet
230
+ ```
231
+
232
+ The goal is not only lower token cost. The useful product outcomes are:
233
+
234
+ - fewer exploratory file reads
235
+ - faster first useful answer
236
+ - better target/test/blast-radius context
237
+ - transparent routing reasons
238
+ - lower model overkill for routine tasks
239
+ - reusable packets for IDEs, CLIs, and other agents
240
+
241
+ ## Install
242
+
243
+ ```bash
244
+ pip install skeletongraph # core: indexing, MCP server, CLI (no API key needed)
245
+ pip install "skeletongraph[llm]" # + litellm for sg run --execute / sg summarize --tier cloud
246
+ pip install "skeletongraph[all]" # everything
247
+ ```
248
+
249
+ ## Quick Start: SG IDE
250
+
251
+ Use this path when you already work inside Cursor, Claude Code, Copilot, Codex,
252
+ Antigravity, or another MCP-capable coding environment.
253
+
254
+ ```bash
255
+ cd your-project
256
+ sg init
257
+ sg build
258
+ sg doctor
259
+ ```
260
+
261
+ `sg init` writes the MCP config and the agent instruction file for the selected
262
+ IDE. SG IDE does not require an API key. Your IDE subscription/model still does
263
+ the reasoning and editing; SkeletonGraph supplies the packet or retrieval
264
+ signals for efficient target selection.
265
+
266
+ Supported IDE setup targets include:
267
+
268
+ | IDE | Integration | Model switching |
269
+ | --- | --- | --- |
270
+ | Cursor | MCP + rules | manual in IDE |
271
+ | Claude Code | MCP + `CLAUDE.md` | `/model` command |
272
+ | GitHub Copilot | MCP + instructions | manual in IDE |
273
+ | Codex | MCP + `AGENTS.md` | manual in agent |
274
+ | Antigravity | MCP + rules | manual in IDE |
275
+ | Windsurf | MCP + rules | manual in IDE |
276
+
277
+ ## Quick Start: SG CLI
278
+
279
+ Use this path when you want a terminal-first context and model-routing pipeline.
280
+
281
+ ```bash
282
+ cd your-project
283
+ sg build
284
+ sg route "fix the auth token validation bug"
285
+ sg prepare "fix the auth token validation bug" --out .skeletongraph/context.md
286
+ sg run "fix the auth token validation bug" --dry-run
287
+ ```
288
+
289
+ `sg route`, `sg prepare`, and `sg run --dry-run` do not need an API key.
290
+
291
+ To call a provider:
292
+
293
+ ```bash
294
+ sg config --cli-provider anthropic
295
+ $env:ANTHROPIC_API_KEY = "..."
296
+ sg run "fix the auth token validation bug" --execute
297
+ ```
298
+
299
+ To test locally without a paid provider key:
300
+
301
+ ```bash
302
+ ollama pull qwen3-coder:latest
303
+ ollama serve
304
+ sg config --cli-provider local
305
+ sg run "fix the auth token validation bug" --dry-run
306
+ sg run "fix the auth token validation bug" --execute
307
+ ```
308
+
309
+ Local execution is intended for cheap pipeline testing. Use provider models for
310
+ quality benchmarks unless the benchmark is specifically for local models.
311
+
312
+ ## Model Dependency, Prewarming, and Keeping the Index Fresh
313
+
314
+ SG downloads **two** small embedding models on first use, both via
315
+ `sentence-transformers` (a hard dependency, not optional):
316
+
317
+ - **`jinaai/jina-embeddings-v2-base-code`** (`SG_DENSE_MODEL`) — the semantic
318
+ leg of `fusion`/`sg_search`. Loaded on `sg warm` or on an agent's first
319
+ dense-retrieval query. Loads with `trust_remote_code=True` (Jina ships custom
320
+ modeling code on the HF Hub) — this executes code from that model repo, same
321
+ as any `trust_remote_code` model.
322
+ - **`all-MiniLM-L6-v2`** (`SG_EMBED_MODEL`) — a smaller, separate model used
323
+ only as a confidence-score tiebreaker at index time. Downloads automatically
324
+ on the **first `sg build`**, not on `sg warm`.
325
+
326
+ Both need internet access the very first time each is used on a machine — after
327
+ that, both are cached locally (Hugging Face's model cache, plus SG's own
328
+ content-hash caches: `.skeletongraph/dense_cache` for the dense leg,
329
+ `.skeletongraph/embeddings.npz` for the confidence tiebreaker) — so later builds
330
+ are incremental: only functions whose text actually changed get re-embedded.
331
+
332
+ **Prewarm before launching an agent**, so that cost lands during setup instead
333
+ of on the agent's first real search:
334
+
335
+ ```bash
336
+ sg build # parse + structural index (no LLM, fast)
337
+ sg warm --path . # prebuild BM25 + dense caches (one-time; minutes on CPU)
338
+ sg warm --path . --mode rerank # skip the dense leg entirely (no embedding cost)
339
+ ```
340
+
341
+ Without this, the first `sg_search` call an agent makes pays the cold-encode
342
+ cost inline — on a large repo this can exceed the dense retrieval leg's
343
+ internal timeout (`SG_DENSE_TIMEOUT_S`, 20s by default), in which case it
344
+ silently degrades to a 2-signal (lexical + structural) result rather than
345
+ failing outright. Prewarming avoids relying on that fallback altogether.
346
+
347
+ **Keeping the index current as files change** — two options, pick based on
348
+ how you work:
349
+
350
+ ```bash
351
+ sg update --path . # one-shot: re-index only files that changed since last build
352
+ sg watch --path . # background daemon: auto-reindexes on save (needs `pip install "skeletongraph[daemon]"`)
353
+ ```
354
+
355
+ `sg watch` is the hands-off option for active development — it debounces
356
+ rapid saves and calls the same incremental update path as `sg update`, so
357
+ editing a file is reflected in the index without a manual rebuild.
358
+
359
+ ## Model Routing
360
+
361
+ SkeletonGraph separates IDE-facing model labels from CLI provider model names.
362
+
363
+ For IDEs, model tiers are recommendations:
364
+
365
+ | Tier | Typical use |
366
+ | --- | --- |
367
+ | SLM | docs, explanations, simple lookup |
368
+ | MLM | normal coding, debugging, tests, review |
369
+ | LLM | architecture, broad migrations, low-confidence tasks |
370
+
371
+ For CLI execution, SkeletonGraph can route to provider model names:
372
+
373
+ ```bash
374
+ sg config --cli-provider anthropic
375
+ sg config --cli-provider openai
376
+ sg config --cli-provider google
377
+ sg config --cli-provider local
378
+ ```
379
+
380
+ Dynamic routing uses task mode, confidence, candidate count, token size, and
381
+ complexity. Code-changing work keeps an MLM floor by default so cost savings do
382
+ not come from making weak models edit code unsafely. Retrieval planning can use
383
+ small models to propose targets over AST/summaries before the heavy model runs.
384
+
385
+ ## IDE Integration
386
+
387
+ After `sg init` and `sg build`, register SG as an MCP server and write IDE hooks:
388
+
389
+ ```bash
390
+ sg install --ide claude-code # Claude Code: hooks + MCP server + CLAUDE.md rules
391
+ sg install --ide cursor # Cursor: MCP + .cursor/rules/skeletongraph.mdc + hooks
392
+ sg install --ide cline # Cline / Roo: MCP config + rules block
393
+ sg install --ide copilot # GitHub Copilot: MCP + copilot-instructions.md
394
+ sg install --ide windsurf # Windsurf: MCP + .windsurfrules
395
+ sg install # auto-detect all installed IDEs
396
+ ```
397
+
398
+ After install, restart your editor. SkeletonGraph runs as a background MCP server
399
+ (`sg serve --path .`) that the IDE connects to automatically.
400
+
401
+ ## MCP Tools
402
+
403
+ Six tools are exposed to the IDE agent. Use these **instead of** grep/glob/file reads:
404
+
405
+ | Tool | When to call | Returns |
406
+ | --- | --- | --- |
407
+ | `sg_overview` | Session start — once per session | Constraints + top-N functions (by PageRank) + recent turns + index stats |
408
+ | `sg_search "query"` | **Primary retrieval** — almost every prompt | Top-3 matches with body excerpts + summaries + 1-hop callers; top-4..N as signatures + summaries. One call usually enough — no need to chain. |
409
+ | `sg_get "fqn"` | When the exact FQN is known | Signature + summary + 1-hop callers + callees |
410
+ | `sg_expand "target"` | When more body is needed than `sg_search` returned | Full function body / file / line range (token-capped) |
411
+ | `sg_constraint list` / `propose` | Before proposing changes | Confirmed + proposed project rules |
412
+ | `sg_log` | Reviewing recent session turns | Last-N turn summaries with files touched |
413
+
414
+ **Smart context routing.** On each `UserPromptSubmit`, SG classifies the prompt
415
+ (architecture / explain / decision / debug / test / review / general) and
416
+ includes the matching MD file from `.skeletongraph/` — e.g. `architecture.md`
417
+ only for design/refactor queries, `project.md` only for "what is this codebase"
418
+ queries. Constraints + session digest + relevant functions are always injected.
419
+
420
+ **Cold start.** If no `.skeletongraph/` index exists when an MCP tool is called,
421
+ SG auto-builds on first invocation (see `auto_build_on_query` in config).
422
+
423
+ ## CLI Reference
424
+
425
+ **Indexing & status**
426
+
427
+ | Command | Purpose |
428
+ | --- | --- |
429
+ | `sg init [--agent cursor]` | Configure project, IDE preset, MCP, constraints |
430
+ | `sg index` | Full index (alias for `sg build`) |
431
+ | `sg index --incremental` | Only re-index changed files |
432
+ | `sg build` | Full index with detailed output |
433
+ | `sg update` | Incremental update |
434
+ | `sg status` | Show index status |
435
+ | `sg doctor` | Check index, routing, provider, Ollama readiness |
436
+ | `sg overview` | Project skeleton: top functions, constraints, session |
437
+ | `sg install [--ide <name>]` | Write IDE hooks + MCP config |
438
+
439
+ **Retrieval**
440
+
441
+ | Command | Purpose |
442
+ | --- | --- |
443
+ | `sg search "query"` | BM25 + graph search (no API key) |
444
+ | `sg get "fqn"` | Get function signature, summary, callers |
445
+ | `sg expand "target"` | Expand function body / file / line range |
446
+
447
+ **Constraints & session**
448
+
449
+ | Command | Purpose |
450
+ | --- | --- |
451
+ | `sg constraint list` | List all constraints |
452
+ | `sg constraint propose "text"` | Add a proposal |
453
+ | `sg constraint confirm <id>` | Promote proposal → decisions.md |
454
+ | `sg constraint remove <id>` | Remove a constraint |
455
+ | `sg constraint aggregate` | Import from IDE rule files |
456
+ | `sg log [--last-n 10]` | Show recent session turns |
457
+
458
+ **Summarization**
459
+
460
+ | Command | Purpose | API key |
461
+ | --- | --- | --- |
462
+ | `sg summarize --tier local` | Ollama Tier-0.5 (free, on-device) | no |
463
+ | `sg summarize --tier cloud` | Cloud LLM Tier-1 | provider key |
464
+ | `sg summarize --tier cloud --force` | Re-summarize all functions | provider key |
465
+
466
+ **Model routing & execution**
467
+
468
+ | Command | Purpose | API key |
469
+ | --- | --- | --- |
470
+ | `sg route "task"` | Show task mode, tier, recommended model | no |
471
+ | `sg run "task" --dry-run` | Plan routed execution | no |
472
+ | `sg run "task" --execute` | Call configured provider | provider or local |
473
+ | `sg config [--agent cursor]` | Configure IDE and CLI models | no |
474
+ | `sg config --cli-provider anthropic` | Set CLI execution provider | no |
475
+
476
+ **Background indexing**
477
+
478
+ | Command | Purpose |
479
+ | --- | --- |
480
+ | `sg watch` | Daemon: auto-reindex files on save |
481
+
482
+ Provider output from `sg run --execute` is written to `.skeletongraph/runs/`.
483
+ Evaluation is currently done externally via SWE-bench harness — see `docs/swe_bench_runbook.md`.
484
+
485
+ ## Python API
486
+
487
+ ```python
488
+ from skeletongraph.engine import SGEngine
489
+
490
+ engine = SGEngine(project_root=".")
491
+ result = engine.query("fix the content-length bug", delivery="cli")
492
+
493
+ print(result.context_text)
494
+ print(result.query_mode)
495
+ print(result.model_tier)
496
+ print(result.recommended_model)
497
+ print(result.routing_reason)
498
+ ```
499
+
500
+ ## Architecture
501
+
502
+ ```text
503
+ src/skeletongraph/
504
+ parser/ AST extraction
505
+ graph/ dependency graph and ranking
506
+ storage/ .skeletongraph persistence
507
+ retrieval/ classification, resolution, model routing
508
+ assembly/ context packet construction
509
+ session/ memory and dedup
510
+ server/ MCP server
511
+ llm/ LiteLLM wrapper for optional CLI execution
512
+ cli/ Click commands
513
+ engine.py unified query pipeline
514
+ ```
515
+
516
+ ## Evaluation
517
+
518
+ The architecture/pipeline blueprint and evaluation plan are in:
519
+
520
+ ```text
521
+ docs/blueprint.md
522
+ docs/evaluation.md
523
+ ```
524
+
525
+ SkeletonGraph should be evaluated on both quality and cost:
526
+
527
+ - target recall and packet completeness
528
+ - missed tests/callers
529
+ - first useful answer latency
530
+ - file reads after SG context
531
+ - pass rate
532
+ - cost per passing task
533
+ - dynamic routing overkill/underpower rate
534
+ - IDE compliance with SG-first context usage
535
+
536
+ Cost savings are only meaningful when reported with pass rate.
537
+
538
+ ## License
539
+
540
+ MIT