Preview documentation.
The intended public workflow for connecting a Python controller, writing a scenario, and gating CI. Names may still tighten before the first public release.
Smethe is not yet published to PyPI. Commands below document the launch candidate; they are not live install instructions. Get the verified release notice.
Mental model
Smethe is a fast behavioral test layer for controller code. A scenario provides a road, actors, observations, and assertions. Your adapter receives each observation and returns a control command. The engine advances a fixed step, derives metrics, evaluates every assertion, and exits non-zero when the gate fails.
scenario.yaml → observations → your controller → controls
↓ ↓
seeded world ← fixed-step functional engine ←┘
↓
assertions + run manifest + local report
The useful unit is a committed scenario with an explicit verdict—not an interactive GUI session. Smethe belongs before physics-heavy SIL, HIL, proving-ground, and road validation.
Controller adapter
The launch interface separates controller code from the engine. A plugin implements two methods and exposes an entry point under smethe.controllers.
from smethe import Control, ControllerAdapter, ControllerContext, ControllerObservation
class TeamAEB(ControllerAdapter):
def __init__(self, ttc_brake: float = 1.8):
self.ttc_brake = ttc_brake
def reset(self, context: ControllerContext) -> None:
self.dt = context.dt
def control(self, observation: ControllerObservation) -> Control:
closing = [
item for item in observation.detections
if item.rel_x > 0.0 and abs(item.rel_y) < 2.0 and item.range_rate < 0.0
]
nearest = min(closing, key=lambda item: item.range, default=None)
ttc = nearest.range / -nearest.range_rate if nearest else float("inf")
return Control(accel=-8.0 if ttc < self.ttc_brake else 0.0, steer=0.0)
The observation contract is typed and versioned. Plugin configuration belongs in the scenario; controller source and dependencies remain in your project environment.
Plugin registration
# pyproject.toml in your controller package
[project.entry-points."smethe.controllers"]
team_aeb = "team_controls.aeb:TeamAEB"
Scenario schema
Every document declares a schema version. Unknown keys and invalid units fail validation instead of silently changing test intent.
schema_version: 1
scenario:
name: aeb_stationary
dt: 0.02
duration: 15.0
seed: 7
road: {type: straight_highway, lanes: 2, length: 2000}
entities:
- id: ego
role: ego
init: {lane: lane0, s: 0.0, speed: 22.0}
controller:
type: plugin
name: team_aeb
sensor: {type: object_list, max_range: 160.0}
config: {ttc_brake: 1.8}
- id: obstacle
role: target
init: {lane: lane0, s: 85.0, speed: 0.0}
evaluation:
ego: ego
assertions:
- {type: no_collision}
- {type: min_distance, threshold: 0.5}
- {type: max_deceleration, limit: 9.5}
A gate must contain at least one assertion. Initial overlap is evaluated at t=0; collision checks consider motion between fixed steps, not only sampled end positions.
Local CLI
The planned command surface is intentionally small:
| Command | Purpose |
|---|---|
smethe init [directory] | Create a starter controller package, scenario, sweep, and CI workflow. |
smethe validate <scenario> | Strictly validate one scenario document, references, and assertions. |
smethe run <scenario> | Run one scenario file or bundled example; exit non-zero on a failed gate. |
smethe sweep <scenario> <sweep> | Run a bounded grid or seeded sample locally. |
smethe report <scenario> | Run one scenario and render a local replay and result summary. |
smethe publish <evidence> | Upload a smethe.evidence/v1 bundle for approved Cloud cohorts. |
# Launch-candidate workflow; package is not public yet
mkdir -p .smethe
smethe validate scenarios/cutin.yaml
smethe run scenarios/cutin.yaml \
--json .smethe/result.json \
--evidence .smethe/evidence.json
# Any failed assertion produces a non-zero process exit.
echo $?
CI gate
Smethe does not need hosted compute for controller execution. Once a verified package is available, a generic CI job installs your controller and Smethe together, runs the scenarios, and preserves structured results.
# Illustrative GitHub Actions step for the public release
- name: Run functional controller gates
run: |
python -m pip install /path/to/verified/smethe-build.whl .
mkdir -p .smethe
smethe validate scenarios/controller_gate.yaml
smethe run scenarios/controller_gate.yaml \
--json .smethe/result.json \
--evidence .smethe/evidence.json
Design partners may then publish the completed evidence bundle from GitHub Actions using short-lived OIDC identity. Long-lived repository secrets are not the preferred GitHub path.
Run manifest
RunManifestV1 records immutable provenance. A local smethe.evidence/v1 bundle joins that manifest with the completion verdict, finite metrics, and assertion outcomes; neither object contains source.
{
"schema": "smethe.run/v1",
"run_key": "github:8675309:1:controller-gate:8c1d5a729c4e",
"scenario_hash": "8c1d5a729c4e918be0a7d32f6b55a6cbd7a1be4002e6f9c449c0fe0bd0db4ef2",
"seed": 7,
"created_at": "2026-07-22T18:42:00Z",
"engine": {
"name": "smethe", "version": "0.1.0",
"python": "3.12.4", "platform": "Linux-x86_64"
},
"git": {
"repository": "acme/controller",
"commit_sha": "6f3a91c",
"ref": "refs/pull/1842/merge",
"pull_request": 1842,
"dirty": false
},
"controller": {"adapter": "team_aeb", "version": "2.4.1"},
"gate": {"name": "controller-regression"}
}
The CLI generates the exact hashes, timestamps, platform values, and run key. Do not add filesystem paths, source fragments, access tokens, raw environment variables, or personal data. The hosted dashboard treats every uploaded field as untrusted structured data.
Deterministic sweeps
A sweep varies one or more scenario values in deterministic order and derives a distinct reproducible seed for every case. The runner retains one result for each variant so JSON and HTML reports can describe individual failures; keep campaign sizes bounded to the memory and CI time available.
schema_version: 1
mode: sample
samples: 500
seed: 41
parameters:
- path: entities[1].init.speed
range: [10.0, 30.0]
- path: entities[0].controller.config.ttc_brake
values: [1.2, 1.6, 2.0]
smethe sweep scenarios/cutin.yaml sweeps/cutin.yaml \
--workers 8 --min-pass-rate 0.99 --json .smethe/sweep.json
Cloud boundary
The hosted service is for pull-request status, evidence history, retention, and team workflow. It is not a remote controller runner.
| Stays in customer CI | May be sent to Smethe Cloud |
|---|---|
| Repository checkout and source | Repository and commit identifiers |
| Controller process and dependencies | Smethe version and scenario hash |
| Secrets and environment values | Gate verdict, metrics, and assertion detail |
| Raw internal datasets | Optional structured report data |
Paid private evidence is planned for 90-day retention with immediate deletion support. The planned free public tier keeps seven days of run metadata. See the security model and privacy notice.
Scope and limitations
Smethe models functional driving behavior using simplified roads, vehicle motion, and idealized sensor detections. It can expose decision-logic regressions quickly, but a passing gate is not proof of real-world safety.
- Use physics-based simulation for photometric camera, lidar, radar, and detailed vehicle effects.
- Use HIL for ECU timing, buses, hardware faults, and production integration.
- Use qualified processes, safety analyses, proving grounds, and road validation where required.
- Validate that each simplified model is appropriate for the question the test claims to answer.
Release status
The public package, repository, and hosted beta are in preparation. The intended core license is Apache-2.0, but the release is not complete until an official repository and verified PyPI distribution are linked here.