Upgrading to 2.0.0¶
Everything 2.0.0 asks of you, in the order it is likely to bite. Most installs need only step 1, and it happens by itself.
2.0.0 is the remediation of a production-readiness audit that scored 1.8.0 45/100 — not ready across
189 findings. A major version is warranted because 47 public contracts changed: tool names, argument
names, result shapes, environment variables, exit codes, and the on-disk layout of .sankshep/. The
changelog lists what changed and why; this page lists what you have to do.
1. Every index rebuilds on first start¶
Applies to: everyone. Action: none, but expect a delay.
Chunks used to be sized by line count (400 lines), while the embedding model reads the first 512 tokens and discards the rest. So a 400-line class was stored under a vector describing roughly its first thirty lines, and a search for something declared halfway down it returned nothing.
Chunks are now sized by what the model can actually read, and anything still larger — including a file in a
language Sankshep has no grammar for — is split into overlapping windows. That moved the chunker version,
so an existing index.db is discarded and rebuilt.
This is correct rather than merely convenient: every vector in an existing index describes only the beginning of its chunk. The index is derived data, so a rebuild is always safe. It takes minutes on a large repository.
You do not have to delete anything. If you would rather do it explicitly, remove .sankshep/index.db and
its -wal/-shm siblings.
2. A scripted search_code caller has to read text, not JSON¶
Applies to: anything that parses search_code output. Action: change the parser.
Hits used to come back as a single JSON line inside a text block, with every newline, quote and tab
escaped — the form a model reads worst, and pure token overhead in a product whose purpose is spending
fewer tokens. The result is now the same shape get_context already used:
// ---- Sankshep search: 2 hits, best first ----
// Pass any path below to get_context for the whole minimized file.
// Calculator.cs:6-28 (Type Calculator)
public class Calculator
{
...
}
Everything a hit carried is still present: path, line range, kind and symbol name, on the // line above
each block. The internal content hash is gone, deliberately — it identified a chunk inside Sankshep's own
index and meant nothing to a caller.
Also: an empty index is now an error, not an empty success. If your code treated
{count:0,results:[]} as "no such code", it was reading an unbuilt index the same way — which is how a
model came to state that code did not exist. Run index_repo first.
3. Helm users behind an Ingress will get 403 until they act¶
Applies to: chart users with an Ingress. Action: one value.
Chart 1.3.0 renders the Host allow-list by default, derived from the release's own Service DNS plus the
loopback names a kubectl port-forward makes a browser send. An Ingress hostname cannot be derived from
anything the chart knows, so it has to be declared:
allowedHosts.enabled: false restores the previous behaviour exactly.
Health probes are exempt either way, so this can never take the pod down — the deployment comes up
healthy and refuses traffic, which is the failure mode you want of the two. NOTES.txt prints the
effective list after install.
4. The first export_decisions fails once, if you already have a DECISIONS.md¶
Applies to: anyone who has run export_decisions. Action: move or rename the old file.
The generated file now carries a marker on its third line:
# Decisions
<!-- Generated by sankshep export_decisions. Edits to this file will be overwritten. -->
A DECISIONS.md without that marker is refused rather than overwritten, because the tool could not
previously tell its own output from a file you wrote by hand — and it overwrote either. Move or rename
yours and re-run; from then on it rewrites its own file as it always did.
5. service install refuses a user-writable binary¶
Applies to: Windows Service installs. Action: install from a protected directory.
A service registered by an administrator runs as LocalSystem, so anyone who can replace its executable
can run code as LocalSystem. dotnet tool install -g puts the binary under your user profile, which
you can write — so installing from there handed that privilege to your own account and to anything running
as you.
The installer now refuses, and names the principal that could replace the file. Copy the binary somewhere only administrators can write, and install from there:
mkdir "C:\Program Files\Sankshep"
copy "$env:USERPROFILE\.dotnet\tools\sankshep.exe" "C:\Program Files\Sankshep\"
& "C:\Program Files\Sankshep\sankshep.exe" service install --repo C:\path\to\repo
6. A supervised service keeps state outside the repository¶
Applies to: Windows Service and systemd installs. Action: copy facts.db if you want to keep it.
Under a service manager, facts.db, index.db and stats.db move from <repo>/.sankshep to a
machine-wide root — %ProgramData%\Sankshep on Windows — and the embedding model moves out of the service
account's profile. Startup names both the old and new paths.
The index rebuilds anyway (step 1). Authored memory is not migrated, and that is deliberate: copying a
file out of an attacker-controllable directory while running as LocalSystem is the defect the move exists
to close. Copy facts.db across by hand if you want your remembered facts.
Interactive runs are unchanged, and so are SANKSHEP_STATE_DIR and SANKSHEP_MODEL_DIR if you set them.
7. A fail-closed refusal now exits 1¶
Applies to: anything that parses the exit code. Action: expect 1.
A refused start — a non-loopback bind with no authentication, most often — used to surface as an unhandled
exception: a .NET stack trace and exit code 0xE0434352, which reads like a crash to a service manager and
to anyone watching a container restart loop. It is now one line on stderr and exit code 1.
Things that changed but ask nothing of you¶
summarize_repocovers every language Sankshep parses, and bounds itself at 20,000 tokens by default, saying so when it truncates. PassmaxTokensto change it; the floor is 500.recallcaps its result set at 50 and reportsmatchedalongsidecount, plustruncated.index_repo'spathis optional and defaults to the whole repo. Its message now describes the walk rather than the index's total, and it reports progress per file when the client sends a progress token.get_context'stokenBudgetis a ceiling on the whole response, header included, and a file larger than the budget is truncated rather than dropped whole.- Raising the log level cannot print your code. See Environment variables.
appsettings.jsonin a served repository is ignored on both transports. If you were configuring Sankshep that way, move those settings to environment variables — but note that a repo-rootappsettings.jsoncould previously re-bind the server to0.0.0.0, which is why it is gone.- An absolute path is refused on the HTTP transport, and by
index_repoon both. Use repo-relative paths, which work everywhere. - Runtime is .NET 10; the MCP SDK is 2.2.0.
If something goes wrong¶
Troubleshooting covers the common cases, and Feedback is the channel for anything it does not.