The problem nobody is measuring
Retrieval quality is not static. It decays.
January: on-call types "checkout timeout" → finds the right runbook ✓
June: the feature is now "payments-core" in docs
on-call still types "the checkout thing"
the runbook never matches → silent miss ✗
Nobody changed the model. Your team changed. Features get renamed, slang accumulates, new docs use new words while old docs use old ones, and the same acronym means two different things to two teams.
Your embedding model can't save you here: your internal names were never on the public internet, so it guesses — and as your language drifts, those guesses rot. No error. No alert. Just retrieval that is a few percent worse every month until someone says "the bot got dumb."
The uncomfortable part: your vocabulary is the one input to retrieval that changes constantly — and no system owns it, versions it, or tells you when it drifts.
That is the gap SkeinRank fills.
Try it in 60 seconds
No Docker. No Elasticsearch. No config file. Just the idea, working:
pip install skeinrank
import skeinrank
# Your team's slang → the words your search engine actually indexed
skeinrank.canonicalize("k8s pg timeout")
# → "kubernetes postgresql timeout"
# Same three letters, two realities — resolved by context, not by guessing
skeinrank.canonicalize("pg timeout") # → "postgresql timeout"
skeinrank.canonicalize("pg layout") # → "page layout"
An embedding model probably gets the first one right. The difference is that SkeinRank doesn't guess — it applies an explicit, versioned, inspectable rule. You can see it, diff it, and roll it back. That distinction is the whole product.
Now point it at your own docs and ask the only question that matters:
# Does your terminology still cover what your team is actually writing?
skeinrank drift-scan ./docs --profile platform_ops
Terminology drift report
covered surfaces 812
NEW unmatched surfaces 47 ← language that entered your docs and nothing maps
top drift: "pcore" (9×) "blue-deploy" (6×) "the checkout thing" (4×)
That report is the magic. It is the thing your embedding model, your synonym file, and your vector DB physically cannot give you: a measurement of how far your live language has drifted from the vocabulary your search relies on.
→ Full walkthrough: docs/guides/terminology-drift-report.md · examples/drift-scan
Proof on a real documentation corpus
We tested cross-version terminology discovery on the public Apache Airflow documentation for releases 2.3.0, 2.7.0, and 3.0.0.
The discovery phase was unsupervised with respect to the target terms: SkeinRank received the selected documentation corpora, but no gold term list, known-renames file, release-note hints, or human labels. Human labels were applied after ranking, only to evaluate the bounded top-10 review output.
| Release window | P@5 | P@10 | Label coverage | Labelled true recall |
|---|---|---|---|---|
Airflow 2.3.0 → 2.7.0 |
40% (2/5) | 20% (2/10) | 100% (10/10) | 100% (2/2) |
Airflow 2.7.0 → 3.0.0 |
100% (5/5) | 90% (9/10) | 100% (10/10) | 90% (9/10) |
The two windows show why terminology discovery needs evidence and review rather than one context-free accuracy claim:
2.3.0 → 2.7.0is a hard incremental window. SkeinRank surfaced the real additionsdb migrateandDataset, alongside pre-existing API names, example-local identifiers, an RST document target, and repeated instructional wording.2.7.0 → 3.0.0contains a clearer vocabulary transition. The first five findings were all true and nine of the top ten were true, includingasset,auth manager,AssetAlias,ObjectStoragePath,asset events,bundles,outlet_events,dag bundles, andJWT.- The known true candidate
airflow.sdkwas discovered by core but excluded by the benchmark's prose-only review policy because all 79 observed occurrences were code context. The report records that exact loss stage instead of silently treating the term as absent.
This is a reproducible documentation-corpus benchmark, not a universal precision claim and not an evaluation of the entire retrieval stack. The exact Airflow commits, corpus settings, context policy, labels, and machine-readable evidence are published in SkeinRank/skeinrank-benchmark.
→ Canonical report · Machine-readable JSON
Why this can't just be a synonym file
Every search engine has a synonym list. A synonym list is configuration. It cannot tell you:
- which version of your terminology is live right now;
- who approved an alias, and what evidence backed it;
- how to roll back a terminology change that hurt retrieval;
- whether your dictionary still covers last month's documents;
- how an AI agent can suggest a fix without write-access to production.
SkeinRank treats your terminology as a governed, versioned, measurable asset — sitting beside the search engine you already run, not replacing it.
raw query ──▶ SkeinRank ──▶ search-ready query ──▶ your Elasticsearch / OpenSearch / vector DB
(canonicalize · disambiguate · pinned snapshot)
It adds one field to your documents and one resolution step to your queries. Your retrieval backend stays exactly where it is.
How the value compounds
The 60-second SDK is the door. Behind it is a full lifecycle that turns drift from an invisible decay into a controlled loop:
detect drift → propose fix → prove with evidence → human approves → versioned snapshot → safe rollout
▲ │
└────────────────────────────── measure retrieval before / after ◀──────────────────────────────┘
Every step is something a flat config file cannot do — and it is exactly what lets a system keep scaling its document volume without letting search quality slide.
| Step | What happens |
|---|---|
| Discover | Find internal terms, acronyms, aliases, and ambiguous surfaces — including drift in recent docs. |
| Prove | Attach evidence from documents, incidents, tickets, and search traces. |
| Govern | Review proposed changes through the AI Inbox and risk-aware policy. |
| Snapshot | Publish immutable, versioned terminology for runtime use. |
| Bind | Apply the right vocabulary to the right search context. |
| Serve | Expose API, SDK, CLI, and MCP tools for search, RAG, and agents. |
| Evaluate | Compare retrieval behavior before and after every terminology change. |
Production changes never touch the database directly — they flow through proposal → validation → risk policy → review → snapshot → rollout. Terminology is treated like code, not like a settings page.
This is where SkeinRank is heading and what the architecture is built for.
As your document volume scales, drift accelerates. SkeinRank lets AI agents — through MCP, scoped credentials, and strict RBAC — continuously watch for drift and propose the fix: "pcore now appears 40× and maps to nothing; suggest aliasing it to payments-core."
Crucially, agents get write-intent without write-access. They submit proposals; they cannot mutate production. A human approves, a snapshot ships, retrieval is re-measured. That is real-time drift control with human-in-the-loop as a hard guarantee, not an afterthought — the part that makes scaling document volume safe instead of scary.
What's in the box
SkeinRank is a terminology sidecar for teams already running Elasticsearch, OpenSearch, vector search, internal doc search, RAG, or AI-agent workflows. Pick the depth you need:
| If you want to… | Capability |
|---|---|
| Stop guessing where your language drifted | Terminology drift reports against live docs |
| Keep ambiguous aliases safe | Context-trigger disambiguation (pg timeout ≠ pg layout) |
| Apply the right vocabulary per index | Binding-aware runtime (profile + index + fields + pinned snapshot) |
| Manage terminology like code | Terminology-as-Code: lint · plan · apply · snapshot via GitOps |
| Approve changes with proof, not vibes | Evidence-assisted review + AI Inbox |
| Ship to search safely | Operator-controlled delivery: preflight · blue/green swap · rollback · pause/resume |
| Let agents help without risk | MCP tools with proposal-only scope |
"But our search tools already have AI now"
They do — inside their own walls. Jira's AI searches Jira. Slack's AI searches Slack. Each learns your vocabulary privately and gives you no reusable layer. That doesn't fix fragmentation — it hardens it, sealing the logic inside models you can't inspect, version, or reuse.
SkeinRank sits underneath those tools: one canonical resolution of your language, as data you own, usable by your RAG, your search, your on-call bot, and your agents alike.
Core model
| Concept | Meaning |
|---|---|
Profile |
Domain terminology: canonical values, aliases, slots, tags, stop lists. |
Binding |
Runtime context: profile + index/alias + fields + target field + pinned snapshot. |
Snapshot |
Immutable, versioned terminology safe to serve or export. |
Proposal |
An agent-, CLI-, or human-submitted change awaiting review. |
Evidence |
Documents, query traces, and risk metadata behind a proposal. |
In production, runtime requests are binding-first — the binding already knows the index, fields, snapshot, and policy:
{ "binding_id": 1, "query": "k8s pg timeout" }
Quickstart paths
| Path | Use when | Start here |
|---|---|---|
| SDK & dictionary | Try the Python SDK, import a synonym file, or draft a dictionary from local docs. | packages/skeinrank-core/README.md · docs/guides/import-dictionary.md · docs/guides/agent-dictionary-assistant.md |
| Drift reports | Check whether your dictionary still covers recent docs and incidents. | docs/guides/terminology-drift-report.md · examples/drift-scan |
| Release stack | Run the public beta from prebuilt GHCR images. | cp .env.example .env && docker compose up -d · docs/deployment/release-compose.md |
| Full dev stack | Build from source with PostgreSQL, ES, RabbitMQ, API, worker, UI. | docs/deployment/docker-compose.md |
| Headless runtime | API/Postgres apply/export and snapshot artifact smoke tests. | docs/deployment/headless-quickstart.md |
| Kubernetes (alpha) | Helm chart on published GHCR images. | charts/skeinrank · docs/deployment/helm-chart.md |
cp .env.example .env
docker compose -f docker-compose.dev.yml up --build -d
make demo-reset
make demo-tour
make demo-tour-smoke
make demo-reset loads the platform_ops profile, creates the platform_knowledge_base index, seeds evidence-backed AI Inbox proposals, and prepares the Playground and Schema & Snapshots views.
Default local URLs: UI http://127.0.0.1:5173, Governance API http://127.0.0.1:8010, Elasticsearch http://127.0.0.1:19200, RabbitMQ http://127.0.0.1:15672.
Walkthroughs: docs/guides/seeded-demo-walkthrough.md · docs/guides/demo-product-tour.md · examples/platform_ops_demo.
Binding-aware endpoints for canonicalization, query planning, and search:
POST /v1/text/canonicalize
POST /v1/query/plan
POST /v1/query/route-plan # read-only: selected/rejected bindings + canonical queries + scores
POST /v1/search
POST /v1/search/multi
Start here: docs/guides/runtime-routing-api.md · docs/guides/context-trigger-disambiguation.md · examples/runtime-routing-api.
YAML outside, JSON inside: people review YAML/JSON dictionaries in Git, the API speaks JSON, PostgreSQL is the control-plane source of truth, and runtime workers consume immutable snapshot artifacts.
cd packages/skeinrank-governance-api
poetry run skeinrank-migrate lint ../../examples/terminology-as-code/platform_ops.dictionary.yaml
poetry run skeinrank-migrate plan ../../examples/terminology-as-code/platform_ops.dictionary.yaml --output plan.json
poetry run skeinrank-migrate apply ../../examples/terminology-as-code/platform_ops.dictionary.yaml --plan-output applied-plan.json
poetry run skeinrank-migrate snapshot-eval --before before.json --after after.json --queries queries.jsonl --output eval.json
Docs: docs/guides/terminology-as-code.md · docs/deployment/gitops-delivery-runbook.md · examples/terminology-as-code.
Elasticsearch/OpenSearch delivery is an advanced, operator-controlled workflow. SkeinRank owns governed terminology artifacts; the search engine stays the retrieval backend. Prefer query-time adapters, vector pre-embedding adapters, and export artifacts; direct backend writes are reserved for explicit operator-controlled delivery.
POST /v1/governance/elasticsearch/bindings/{binding_id}/dry-run
POST /v1/governance/elasticsearch/bindings/{binding_id}/jobs/preflight
POST /v1/governance/elasticsearch/jobs/{job_id}/pause | resume | cancel | rollback
Runbooks: docs/guides/elasticsearch-enrichment.md · docs/deployment/blue-green-alias-swap-runbook.md · docs/concepts/search-integration-scope.md.
A dependency-light MCP stdio adapter exposes proposal-safe tools only: agents can inspect, validate, and submit proposals — they cannot publish snapshots or mutate runtime.
cd packages/skeinrank-governance-api
poetry run skeinrank-mcp --print-tool-manifest
poetry run skeinrank-mcp --smoke-test
skeinrank_list_bindings · skeinrank_explain_query · skeinrank_validate_alias
skeinrank_submit_alias_proposal · skeinrank_get_proposal_status
Docs: docs/deployment/mcp-integration-kit.md · docs/deployment/mcp-claude-desktop.md · docs/deployment/mcp-langgraph-agents.md · examples/mcp-integration-kit.
Benchmarks
Deterministic benchmark and pilot workflows, no OpenRouter or production data required by default.
| Area | Commands / docs |
|---|---|
| Headless benchmark | make benchmark-reset · benchmark-eval · benchmark-report; docs/benchmarks/headless-agent-workflow.md |
| Retrieval eval | make benchmark-retrieval-eval · benchmark-retrieval-compare; docs/benchmarks/retrieval-eval-baseline.md |
| Performance report | make benchmark-performance-report; docs/benchmarks/cost-latency-throughput-report.md |
| Cross-version terminology discovery | SkeinRank/skeinrank-benchmark · fully labelled Airflow top-10 reports |
| First-company pilot | make pilot-plan; docs/pilots/elasticsearch-pilot-integration.md |
Docker & Kubernetes
Release images publish to GHCR via .github/workflows/docker-publish.yml on v* tags.
docs/deployment/docker-compose.md— full local dev stackdocs/deployment/release-compose.md— GHCR release stackdocs/deployment/helm-chart.md·docs/deployment/helm-production.md— Kubernetes- Ops:
docs/deployment/observability.md·docs/deployment/backup-restore.md·docs/deployment/upgrade-guide.md
Documentation map
Repository layout
packages/skeinrank-core Python SDK, CLI, extraction, canonicalization
packages/skeinrank-server FastAPI runtime wrapper
packages/skeinrank-provider-elasticsearch Elasticsearch provider & enrichment CLI
packages/skeinrank-governance SQLAlchemy/Alembic governance foundation
packages/skeinrank-governance-api FastAPI control-plane API, workers, MCP adapter
packages/skeinrank-ui React/TypeScript governance console
examples/ SDK, drift-scan, migration, coverage, MCP, agents
docs/ Product, concept, guide, API, deployment docs
charts/skeinrank Alpha Helm chart
Repo hygiene:
python -m pip install -r requirements-dev.txt
pre-commit install && ruff check . && ruff format --check .
Community
- Issues — reproducible bugs, failing commands, docs mistakes, concrete tasks.
- Discussions — questions, ideas, architecture, integration feedback, public-beta talk.
Project status
SkeinRank is an active open-source platform preview, not a hosted SaaS. Current focus: binding-aware runtime canonicalization, terminology drift detection, safe governance, AI Inbox review, Terminology-as-Code, MCP agent integration, and operator-controlled Elasticsearch/OpenSearch delivery.
License
Apache-2.0. See LICENSE.
No comments yet
Be the first to share your take.