Wire contract
The wire between the SDK and the Roboticks platform is JUnit XML extended withroboticks.* properties. Nothing else is required — no custom upload protocol, no proprietary metadata. If your test runner emits JUnit, it can speak Roboticks.
This page is a tutorial. For the authoritative schema (XSD + JSON Schema), see the SDK wire contract reference.
What the SDK emits
For a single Python test (schema version 2):- Schema version sits on the
<testsuite>. Per-testcase properties carry the semantic payload; suite-level properties carry the metadata about the emitter. roboticks.confirmsis comma-separated. Standard JUnit properties are stringly-typed; a single comma-list is more portable than nested elements.roboticks.nodeid(added in v2) is what the platform uses to lay out per-test-case S3 folders. The hash slug it derives —sha256(nodeid)[:16]— becomes the sub-directory undertest-runs/{run_id}/test-cases/.roboticks.attach.{kind}(added in v2) is repeatable — one property per file registered withattach_artifact(). The runner uploader walks everyroboticks.attach.*property and posts each file to the per-test-case S3 prefix.
The properties
| Property | Scope | Format | Meaning |
|---|---|---|---|
roboticks_schema_version | suite | integer | Schema version this XML conforms to. Currently 2. |
roboticks.sdk.version | suite | semver | SDK version that produced the XML. |
roboticks.python.version | suite | semver | Interpreter version (Python tests only). |
roboticks.nodeid | testcase | pytest nodeid | Stable identity for the test. Drives the per-test-case S3 prefix. (v2+) |
roboticks.confirms | testcase | comma list | Requirement IDs this test confirms. |
roboticks.tags | testcase | comma list | Free-form tags from @tags(...). |
roboticks.deadline_ms | testcase | integer | Deadline in ms from @deadline(...). |
roboticks.requires_sim | testcase | engine or engine:gpu | Sim requirement from @requires_sim(...). |
roboticks.fault_injection | testcase | JSON | Fault primitives invoked, with topic + params. |
roboticks.mcap.path | testcase | string | Relative path to MCAP file if mcap_capture was used. |
roboticks.attach.{kind} | testcase | string (local path) | Repeatable; one per file registered via attach_artifact(). Kind goes into the S3 sub-folder. (v2+) |
schemas/junit_with_confirms.xsd in the SDK repo.
Per-test-case S3 layout (v2)
When the runner uploads artifacts, schema-2 metadata lets the platform fan files out into per-test-case sub-folders inside the run’s S3 prefix:roboticks.nodeid; no round-trip is required. The workspace UI groups files under whichever test produced them, and rbtk test files --nodeid / rbtk test cases let you scope a download to a single test.
The test-result JSON
For systems that prefer JSON to XML (the platform’s internal store, the LLM triage prompt context, the matrix API), the platform converts JUnit-with-confirms into a JSON shape defined atschemas/test_result.schema.json:
Schema versioning
Schema versions are integers. Every increment is a breaking change to either the XML or the JSON shape. The platform supports the current version and one back.| Version | Status | Notes |
|---|---|---|
| 2 | current | Adds roboticks.nodeid (required) + roboticks.attach.{kind} (optional, repeatable). Enables per-test-case S3 layout. |
| 1 | supported (legacy) | Initial GA. Still accepted; per-test-case artifacts fall back to the run-level prefix. |
| 0 | rejected | The pre-GA testing builds; never produced by a released SDK |
The handshake
When the platform parses an uploaded JUnit XML, the first thing it does is readroboticks_schema_version from the suite properties:
The forward-compat behaviour matters: a newer SDK MAY upload a newer schema; the platform tolerates unknown roboticks.* properties rather than failing. You can upgrade the SDK ahead of a platform release without breaking your pipeline.
Conversely, the platform never downgrades. A schema-1 platform will not produce schema-0 JSON.
What if I’m using a non-Roboticks test framework
If you emit stock JUnit (withoutroboticks_schema_version), the platform still ingests the file. You get:
- Test pass/fail in the Check Run.
- No requirement linking (the matrix shows the test under “Unlinked”).
- No deadline, no tags, no MCAP correlation.
@confirms to each test. Even a <property name="roboticks.confirms" value="REQ-001"/> written by hand into the JUnit XML works. The SDK is the convenient path, not the only path.
Next
SDK wire contract reference
Authoritative schema with XSD and JSON Schema files.
Pytest plugin internals
How the SDK actually writes those properties.
CI recipes
How to get the XML to the platform.
Matrix UI
Where the parsed
confirms show up.