osr-contributing
.claude/skills/osr-contributing/SKILL.md
Work inside the OpenSmartRoute repository itself. Add a new strategy, signal, adapter or module to the codebase under src/opensmartroute; update the frozen public API snapshot in tests/public_api.json; keep the version literal and pyproject in sync; pass the ruff, mypy and pytest quality gates and the docs gate (docs/REFERENCE.md regenerated, every docs/*.md linked from README); write or update docs/*.md and .claude/skills SKILL.md packages so they render on the documentation site; follow the zero-dependency, settings and branding single-source-of-truth rules and the design patterns; write tests and CHANGELOG entries; prepare a release. Use when contributing code or documentation to the repo, fixing a failing gate, or reviewing a pull request against project conventions.
- Package
- .claude/skills/osr-contributing
- Compatibility
- OpenSmartRoute repository, Python >= 3.10
- License
- Apache-2.0
- Domains
- coding
- Quality prior
- 0.9
- Tags
- opensmartroute contributing repo conventions
Install by copying .claude/skills/osr-contributing/ into the skills folder of your coding assistant. To load every package as a routing target: osr --skills .claude/skills route "..." --plan.
Gates (run all four before finishing any change)#
python -m ruff format src tests
python -m ruff check src tests # rules E,F,I,UP,B,S; line length 120
python -m mypy src # mypy_path=src, packages=opensmartroute; must be clean
python -m pytest tests -q # pythonpath=src
python scripts/api_reference.py # regenerate docs/REFERENCE.md after any public-name change
tests/test_docs.py fails when docs/REFERENCE.md is stale or an exported name has no summary;
python scripts/api_reference.py report lists the undocumented names. It also requires every
docs/*.md to be linked from README.md and every .claude/skills/<name>/ to contain a SKILL.md.
tests/test_docs_claims.py (SDK) and platform/api/tests/test_platform_docs_claims.py (platform) fail when a
doc names an osr command / flag, an OSR_* variable, an HTTP endpoint or a /platform/dashboard/<page> that
does not exist, when a user-facing doc is missing from the site catalogue, or when a CHANGELOG section
lacks a date, body or compare link - fix the doc or the code, never the test.
Ad-hoc scripts: $env:PYTHONPATH="src"; python -X utf8 ... (the package is not installed in the venv).
Hard rules#
- Zero runtime dependencies in the core. Anything optional (
yaml,fastapi,httpx,sentence_transformers,opentelemetry,cryptography) is imported lazily inside the function that needs it and mapped to an extra inpyproject.toml(yaml,server,embeddings,otel,crypto,all). - Public API is frozen.
tests/public_api.jsonsnapshotsopensmartroute.__all__. Adding a name = add it to the JSON (sorted; uppercase first, then__version__, then lowercase). Removing or renaming = major version bump. - Version literal.
__version__ = "x.y.z"stays a literal insrc/opensmartroute/__init__.pyand must equalversion = "x.y.z"inpyproject.toml(scripts/release.pyrewrites both). Read it elsewhere throughbranding.version(). - No hardcoded tunables. Thresholds, weights, scales go in
settings.pydataclasses and are read throughresolve(settings).<group>.<field>; document new fields (they becomeOSR_<GROUP>_<FIELD>automatically). - No brand literals. Use
branding.PACKAGE / CLI / env_key / error_code / metadata_key / logger / user_agent.osr-*metadata keys come frommetadata_key(field). - Typed errors only. Raise subclasses of
OpenSmartRouteError(ConfigurationError,ValidationError,NoRouteError,TargetUnavailableError,ExecutionError,SecurityError,StateStoreError) withdetails={...}; never bareException. - Every exported name is documented. Classes and functions carry a one-line docstring; module-level
constants and type aliases carry a same-line
# comment(or a comment on the line above). The first line becomes its row indocs/REFERENCE.md. - Strategies must degrade to neutral scores on internal failure, not raise during
route().
Where things go#
core/ types + TargetRegistry strategies/ Strategy subclasses (name = snake_case noun)
signals/ SignalExtractor subclasses policy/ PolicyRule callables + Policy chain
math/ pure numerics, no routing types learning/ learners that persist state
realtime/ breakers, budgets, health enterprise/ builder, middleware, telemetry, stores, ops
security/ guards, limits, provenance adapters/ external systems; lazy optional imports
eval/ datasets, metrics, frontiers sdk.py ComponentRegistry + decorators
observability.py Tracer, Span, Event, sinks (emit with current_tracer().event(...); names in EVENT_NAMES)
settings.py tunables branding.py names (leaf module, imports nothing internal)
Adding a strategy#
- Subclass
Strategyinstrategies/<name>.py; setname; implementscore(request, signals, candidates) -> dict[str, StrategyScore]; optionalupdate(outcome),state()/load_state()for persistence. - Take
settings: Settings | None = None; add aWeightSettings.<name>default. - Export from
strategies/__init__.py(__all__) and, if public,opensmartroute/__init__.py+tests/public_api.json. Add todefault_strategies()only if it needs no external service. - Tests: deterministic (
seed=0), one behavioural test + one persistence round-trip if stateful. - Document in
docs/ARCHITECTURE.md(strategies table) andREADME.md"Strategies"; CHANGELOG under[Unreleased]; runpython scripts/api_reference.pysodocs/REFERENCE.mdpicks it up.
Adding an adapter#
Return RouteTargets or handlers; never import the optional client at module import time; validate
external input (ConfigurationError with details["path"]), pass descriptions through
security.description_risk when they come from a third party.
Documentation#
- Layout:
README.mdshort overview;docs/GUIDE.mdwalkthroughs (numbered H2s);docs/SDK.mddecorator SDK and settings;docs/ARCHITECTURE.mdpipeline and strategies table;docs/MATH.mdnumbered sections with module references;docs/RESEARCH.mdidea-to-module map;docs/ROADMAP.mdrows name the module;docs/REFERENCE.mdis generated - never edit by hand and never> docs/REFERENCE.md(the script writes it). - The Next.js documentation site (
platform/web,/docs/<slug>) is end-user documentation for the hosted platform, the Python SDK and the pip package. It publishesdocs/*.md(docs/PLATFORM.mdis the platform user guide), the rootREADME/CHANGELOG/CONTRIBUTING/SECURITY,deploy/README.md,spec/ocm/README.md, every.claude/skills/*/SKILL.mdand a REST API reference generated fromplatform/api/openapi.json. Internal documents (docs/PLATFORM_PLAN.md,docs/GO_TO_MARKET.md,docs/BRAND.md,docs/sales/*.md,platform/README.md) stay in the repository and are linked fromREADME.mdonly. A new user-facingdocs/*.mdneeds an entry inplatform/web/src/lib/docs/catalogue.tsand a link inREADME.md; skills are discovered automatically. Details: theosr-platformskill andplatform/README.md. - Markdown that renders well on the site: one H1, H2/H3 headings (they become the table of contents and
the search index), GitHub-flavoured tables, fenced code with a language,
```mermaidfor diagrams, relative links to other.mdfiles (rewritten to site routes) and to source files (rewritten to GitHub). Do not rename headings that other files link to without updating the anchors. - Skill packages:
.claude/skills/<name>/SKILL.mdwith frontmattername(= directory),description(<= 1024 chars, several request-like sentences - they are the similarity examples),license,compatibility,metadata.osr-domains(ontology names only, e.g.coding general),osr-tags,osr-quality-prior(0.8-0.95),osr-primary: "false". Omitosr-actions. Add a representative query totests/test_skills.pythat must select the new skill for the plan slot;osr skills .claude/skillsvalidates the folder.
Tests#
tests/test_router.py,test_math.py,test_security.py,test_enterprise.py,test_adapters.py,test_execution.py,test_sdk.py,test_integrations.py,test_public_api.py.- Use
tmp_pathfor state,monkeypatchfor env,ComponentRegistry()instances rather than the globalcomponents; restoreconfigure(before)in afinallywhen touching settings.
Release#
Edit CHANGELOG.md [Unreleased] as you go (Added / Changed / Fixed). scripts/release.py (run by the
Prepare release workflow) bumps the version literal in both files and dates the section; the
release.yml workflow publishes. Do not hand-edit released sections. scripts/release.py readiness
computes the v1.0 readiness table (ROADMAP) from the repo - release rows block check for 1.x, adoption
rows (docs/SECURITY_REVIEW.md review log, examples/leaderboard/results/README.md Listings rows with
accepted, ADOPTERS.md Production users rows) are tracked only. Never fake a row - the table is the
honest state of 1.0. Version mirrors outside release.py prepare: platform/api/{pyproject.toml (version and
opensmartroute[...]>=), osr_platform/init.py}, platform/web/package{,-lock}.json (top two entries),
deploy/helm/opensmartroute/Chart.yaml (version + appVersion), azure.yaml template@, deploy/Dockerfile and
deploy/README.md image tags, README OSR_VERSION=, docs/sales/DEMO_SCRIPT.md, docs/SECURITY_REVIEW.md
subject; then regenerate platform/api/openapi.json and docs/REFERENCE.md.