Launch interface · schema v1

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.

Package status
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:

CommandPurpose
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 CIMay be sent to Smethe Cloud
Repository checkout and sourceRepository and commit identifiers
Controller process and dependenciesSmethe version and scenario hash
Secrets and environment valuesGate verdict, metrics, and assertion detail
Raw internal datasetsOptional 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.

Get the verified release notice Ask a technical question