Deterministic code context from symbol graphs — not vector search
Project description
Stubborn
Deterministic code context from symbol graphs — not vector search.
Status: Beta (Java-first) — release
0.9.0b2· BETA.md
Stubborn compiles a live codebase into type-safe, privacy-preserving stub text for LLMs and agents. It uses SCIP symbol indexes and dependency graphs instead of vector chunking, so context is stubborn: exact, reproducible, and stripped of method bodies.
Independent project under stubborn-ai. Not migration-only — any live project benefits. Optional integration with anchor-migration (see examples/migration-bridge).
Why Stubborn?
| Problem | Vector RAG | Stubborn |
|---|---|---|
| Type hallucinations | Common | Stub signatures from symbol graph |
| Token cost | Full files / arbitrary chunks | Pruned declaration stubs (~80–90% savings target) |
| Privacy | May leak business logic | No method bodies by design |
| Reproducibility | Embedding drift | Same SCIP → same context |
Stub = skeleton declarations (like header files).
Stubborn = refuses to guess — only ships what the symbol graph proves.
Use cases
- Copilot / Cursor agents —
getContext(class)before code generation - Large-repo onboarding — dependency skeleton for one target symbol
- PR semantic audit —
difftwo SCIP indexes after a refactor - Legacy migration — optional consumer of anchor-migration (see examples/migration-bridge)
Requirements
Docker quick start
docker compose build
docker compose run --rm e2e # demo-spring E2E
docker compose run --rm petclinic-e2e # spring-petclinic scale-up
docker compose run --rm cli --help
See docker/README.md.
Installation
PyPI: stubborn-stub · CLI: stubborn (alias: stub)
pip install stubborn-stub[mcp]
From source (development):
git clone https://github.com/stubborn-ai/stubborn.git
cd stubborn
pip install -e ".[dev]"
Quick start
Full E2E with a modern Spring Boot demo: see examples/demo-spring.
1. Index symbols
# Binary SCIP from scip-java (recommended)
stubborn index --scip index.scip --out ./metadata/symbols.db
# Or use the bundled fixture while bootstrapping
stubborn index \
--scip examples/fixtures/minimal.scip \
--out ./metadata/symbols.db
2. Inspect
stubborn info ./metadata/symbols.db
3. Get LLM context for a target symbol
stubborn context ./metadata/symbols.db \
--target "semanticdb maven com/example/OrderService#process()." \
--out ./context/order-service.stub.java
# Compact cross-language format (~fewer tokens):
stubborn context ./metadata/symbols.db \
--target "semanticdb maven com/example/OrderService#process()." \
--format stubborn-dsl \
--out ./context/order-service.stubborn-dsl
See docs/STUBBORN-DSL.md for the compact cross-language format.
Tune output granularity: --member-signatures off|target|neighbors|all, --javadoc off|summary|full (guide).
Or use the short CLI alias: stub.
4. Reconcile before/after (CI-friendly)
stubborn diff ./metadata/before.db ./metadata/after.db
# exit 1 if symbols are missing
5. MCP server (Cursor / agents)
pip install -e ".[mcp]"
export STUBBORN_DB=./metadata/symbols.db
stubborn mcp
Tools: get_context, list_symbols, metrics. See docs/MCP.md for Cursor configuration.
CLI
| Command | Description |
|---|---|
init-db |
Create empty SQLite symbol graph |
index |
Ingest SCIP (.scip, .scip.ndjson, or .json fixture) |
info |
Index run summary |
context |
Prune graph → emit LLM context (--format java-stub | stubborn-dsl) |
metrics |
Compression KPI: stub vs full Java sources |
mcp |
Run MCP server (stdio) for agents |
diff |
Symbol set reconcile (missing/extra) |
Architecture
[Source code] → scip-java / scip-clang / … → index.scip
↓
stubborn index → SQLite symbol graph
↓
stubborn context → stub text (java-stub or stubborn-dsl)
↓
LLM / Agent / CI
SQLite schema: src/stubborn/store/schema/v1.sql
Roadmap
| Version | Focus |
|---|---|
| 0.1 | SQLite schema, JSON fixture ingest, Java stub weaver, CLI shell |
| 0.2 | Binary .scip protobuf ingest, .scip.ndjson, scip-java compatible |
| 0.3 | Token budget enforcement, metrics KPI, weaver quality, Docker CI |
| 0.4 | MCP server (get_context, list_symbols, metrics) |
| 0.5 | Type-neighbor pruning, PR symbol-diff Action, context guard |
| 0.6 | spring-petclinic scale-up E2E (~90% savings) |
| 0.7 | Stubborn-DSL weaver (--format stubborn-dsl) |
| 0.8 | Java-first beta track — BETA.md, demo-spring cases |
| 0.9 | Method signatures, STUBBORN-DSL-GUIDE |
| 0.9.0b2 (now) | Java-first Beta — classifier + weave granularity switches |
| 1.0 | Multi-language E2E, stable API |
Documentation
| Doc | Description |
|---|---|
| docs/README.md | Documentation index |
| docs/STUBBORN-DSL.md | Stubborn-DSL grammar |
| docs/STUBBORN-DSL-GUIDE.md | java-stub vs stubborn-dsl decision guide |
| docs/STUBBORN-DSL-LLM.txt | LLM system-prompt snippet |
| docs/MCP.md | Cursor / agent integration |
| docs/SCIP-INGEST.md | SCIP ingest |
| examples/README.md | E2E examples |
Related projects
| Repo | Role |
|---|---|
| db-metadata | Database schema SSOT |
| java-ast-ssot | Full Java AST SSOT (human + rewrite) |
| stubborn (this repo) | LLM context compiler |
| migration-hub | Program docs; ADR-010 integration contract |
See docs/POSITIONING.md and docs/INTEGRATION.md.
Development
pip install -e ".[dev]"
pytest -v
MCP server:
pip install -e ".[mcp]"
stubborn mcp
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stubborn_stub-0.9.0b2.tar.gz.
File metadata
- Download URL: stubborn_stub-0.9.0b2.tar.gz
- Upload date:
- Size: 36.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d836f81ffa217a30db49f783e997965e1fdf2804af566ceda5fea7e5daef34e1
|
|
| MD5 |
43b3fb8b559fd7ce34dbee00739fef41
|
|
| BLAKE2b-256 |
118dc052899a25473223c5b66192c85fc0636754251e673a4484ef1cee8902ab
|
File details
Details for the file stubborn_stub-0.9.0b2-py3-none-any.whl.
File metadata
- Download URL: stubborn_stub-0.9.0b2-py3-none-any.whl
- Upload date:
- Size: 42.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c09662496e34fdee89d6443c552b9969cf1fd934e6c31d1db00937bc68c75690
|
|
| MD5 |
fbda1b1bfb00598275f3ef02f9821810
|
|
| BLAKE2b-256 |
3db0c300968ac8cc11d2febea64533ea6d675e6aef4890de360d971aff94cd22
|