v0.3.0 — Python support via a pyright-backed COMPILER tier
Sonde now indexes Python, alongside TypeScript and Swift.
npm install -g @cheppulabs/sonde
cd your-python-project
sonde init --resolveRead this before pointing it at Python
Two limitations, stated up front because they are cheap to disclose now and
expensive to discover later.
Python needs --resolve. Without it, Python indexes at the tree-sitter tier
only, which measured 62.81% unresolved reference sites on a real 56-file
project and 57.39% on pydantic — far past the 30% ceiling this project requires
before it will call a language supported. That tier is not fit for structural
queries, and Sonde shipped Python only once a compiler-backed tier cleared the
bar. sonde init --resolve is the supported path.
The gate measured placement, not correctness. It asked whether a reference
found a target, not whether the target was the right one. TypeScript's edges
are scored against tsc in ORACLE.md;
Python has no equivalent oracle, because the only available authority is the
same pyright that produced the edges — scoring them against it would measure
nothing. So Python edges are unverified for target correctness. If you find
a wrong one, that is a known gap rather than a surprise, and worth an issue.
The margin is thin on the worse corpus. 27.00% unresolved against a 30%
ceiling, and 29.72% once a known upward bias is fully reversed — roughly three
references from failing. Full arithmetic in
probes/python-placement/FINDINGS.md.
What the numbers actually are
Unresolved reference sites, measured against thresholds committed before the
measurement ran, on two real corpora:
| Corpus | Tree-sitter only | With --resolve |
|---|---|---|
| A 56-file application | 62.81% | 27.00% |
| pydantic (441 files) | 57.39% | 17.42% |
The first row is why the tree-sitter-only tier was built, measured, and then
refused registration. The gate exists to be able to say no, and it did.
How it works
A bundled pyright drives a COMPILER tier over LSP. No Python interpreter is
required — pyright is a TypeScript program and bundles typeshed — and Sonde
never loads a type checker from your repository, in any language.
Requests are issued serially, because throughput was measured flat across client
concurrency 1, 8, and 32: the server answers on one thread, so a scheduler would
have added complexity and returned nothing. That measurement is why this feature
is small (probes/pyright-feasibility/FINDINGS.md).
Also fixed
- Python stable keys are now guaranteed unique. Indexing pydantic failed
outright withUNIQUE constraint failed: symbol.stable_key. The 88 collisions
came from four distinct causes, each needing different treatment and none
permitted to use a line number: module-level rebinding is one variable,
@overloadfamilies are one runtime function, property accessors earn
role-suffixed keys (area,area@setter), and genuine redefinitions take an
ordinal that survives line moves. - The Swift SDK
EXTERNALfallback is scoped to Swift. It fired on any
reference carrying a scope hint, so Python names colliding with the Swift
table (append,Task,String,Int,filter) would have been attributed
to Swift frameworks — and sinceEXTERNALis excluded from the placement
denominator, that would have biased Python's own gate toward passing.
Install size
pyright is now a pinned hard dependency (~19 MB), matching how the TypeScript
compiler is already bundled. TypeScript-only users carry it without using it;
that trade was made deliberately so --resolve works with no extra setup step.
Full detail in CHANGELOG.md.