> ## Documentation Index
> Fetch the complete documentation index at: https://docs.roboticks.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Overview

> The roboticks SDK ships ROS2-aware test decorators, rclpy assertion helpers, fault injection, and MCAP capture for Python; gtest macros and a confirms registry for C++.

# SDK overview

The Roboticks SDK is the only ROS2-specific code in the product. The platform itself is ROS-version-agnostic; the SDK is what gets your tests speaking the [wire contract](/sdk/wire-contract) the platform parses.

<Info>
  **The SDK is the boundary.** Inside the SDK we know about rclpy, MCAP, Gazebo. Outside (in the platform, in the matrix, in evidence packs) we only know about the wire contract. Cross that line cleanly and everything else composes.
</Info>

## What ships

| Component       | Language | Distribution                                | Repository                                                                             |
| --------------- | -------- | ------------------------------------------- | -------------------------------------------------------------------------------------- |
| `roboticks`     | Python   | [PyPI](https://pypi.org/project/roboticks/) | [github.com/roboticks-io/roboticks-sdk](https://github.com/roboticks-io/roboticks-sdk) |
| `roboticks_cpp` | C++17    | `ament_cmake` package                       | Same repo, `cpp/` directory                                                            |

Both are versioned together — a `0.1.x` Python release and a `0.1.x` C++ release agree on the schema version and the registry contract.

## What's in the Python package

```python theme={null}
from roboticks import (
    confirms, tags, deadline, requires_sim, mcap_capture,
    attach_artifact, KIND_MCAP, KIND_LOGS, KIND_ATTACHMENTS,
)
from roboticks.assertions import (
    assert_topic_published, assert_service_response,
    assert_action_result, assert_param_equals, assert_tf_transform,
)
from roboticks.fault_injection import (
    drop_messages, delay_messages, kill_node, corrupt_topic,
)
from roboticks.launch_testing import (
    make_node_action, generate_test_description, spin_node,
)
```

| Module                      | Purpose                                                                 |
| --------------------------- | ----------------------------------------------------------------------- |
| `roboticks.decorators`      | `@confirms`, `@tags`, `@deadline`, `@requires_sim`                      |
| `roboticks.assertions`      | rclpy-aware assert-and-wait helpers                                     |
| `roboticks.fault_injection` | drop / delay / kill / corrupt context managers                          |
| `roboticks.mcap_capture`    | per-test MCAP recording context manager                                 |
| `roboticks.artifacts`       | `attach_artifact()` — per-test file uploads (mcap / logs / screenshots) |
| `roboticks.launch_testing`  | thin wrappers around the ROS2 launch\_testing module                    |
| `roboticks.pytest_plugin`   | pytest11 entry-point plugin (loaded automatically)                      |
| `roboticks.reporters`       | JUnit-with-confirms writer; CLI stitcher entrypoint                     |

<h3 id="attach_artifact">
  `attach_artifact()`
</h3>

Register an arbitrary file as a per-test artifact for upload alongside JUnit. Use it when a test produces a screenshot, a generated report, a coredump, an extra log, or any other file that should land next to the MCAP in the audit trail.

```python theme={null}
from roboticks import attach_artifact, capture_mcap, KIND_MCAP

def test_obstacle_detection(node):
    with capture_mcap(node) as mcap_path:
        # ... drive the test ...
        pass
    attach_artifact(mcap_path, kind=KIND_MCAP)
    attach_artifact("/tmp/before.png", kind="attachments")
    attach_artifact("/tmp/after.png",  kind="attachments")
    attach_artifact("/tmp/decision_log.jsonl", kind="logs")
```

The SDK only **records** the path — the actual upload happens later (in the cloud-runner agent for cloud runs, in `rbtk` for local runs). Each attachment becomes one `roboticks.attach.{kind}` property on the testcase (see the [wire contract](/sdk/wire-contract#test-case-properties)), and the platform lands files at:

```text theme={null}
test-runs/{run_id}/test-cases/{sha256(nodeid)[:16]}/{kind}/{filename}
```

`kind` is any single URL-safe path segment. Reserved values for the common cases:

| Constant                     | Value           | Use for                             |
| ---------------------------- | --------------- | ----------------------------------- |
| `KIND_MCAP`                  | `"mcap"`        | MCAP bag files                      |
| `KIND_LOGS`                  | `"logs"`        | Log dumps, JSONL traces             |
| `KIND_ATTACHMENTS` (default) | `"attachments"` | Screenshots, reports, anything else |

Called outside a pytest context (e.g. from a helper or fixture not bound to a test function), pass `test_func=` explicitly; otherwise the plugin's thread-local resolution finds the active test.

Full module map: [SDK modules](/sdk/modules).

## What's in the C++ package

```cmake theme={null}
find_package(roboticks_cpp REQUIRED)
target_link_libraries(my_tests roboticks_cpp::roboticks_cpp)
```

```cpp theme={null}
#include <roboticks_cpp/confirms.hpp>     // ROBOTICKS_CONFIRMS, ConfirmsRegistry
#include <roboticks_cpp/assertions.hpp>   // assert_topic_published, etc.
```

`roboticks_cpp` is a **header-only INTERFACE** library so it adds zero compile time outside the test target. The registry has a single inline definition; thread safety is guaranteed by an internal `std::mutex`.

Full C++ surface: [C++ reference](/sdk/cpp-reference).

## Why the SDK is a separate repo

The product splits into three repos for a reason:

```mermaid theme={null}
%%{init: {"theme": "neutral", "themeVariables": {"primaryColor": "#4040ff"}} }%%
flowchart LR
    SDK["roboticks-sdk<br/>(public, OSS)"] -->|JUnit-with-confirms| Plat["Roboticks Platform<br/>(closed)"]
    Run["roboticks-runner<br/>(public, OSS)"] -->|results| Plat
    Plat -->|GitHub Check Runs| GH["GitHub"]
```

* **Public + OSS** means every audit trail is reproducible without proprietary tooling — important to regulators.
* **Independent versioning** lets the SDK move at the cadence of ROS2 distros (yearly), while the platform iterates weekly.
* **Wire contract as the API** means we can rewrite the SDK in v2 without rewriting the platform.

## ROS-version-agnostic

The Python package installs cleanly on a host **without ROS2** — rclpy imports are guarded behind try-blocks and raise a clear error only when an assertion helper is actually called. You can `pip install roboticks` on macOS for local linting, on a CI image without ROS2 for non-ROS test suites, and on a ROS2 Humble/Iron/Rolling box for the real thing.

```python theme={null}
# Works on macOS without rclpy installed:
from roboticks import confirms

@confirms("REQ-100")
def test_pure_python_logic():
    assert 2 + 2 == 4

# Raises informative RuntimeError at call time, not import time:
from roboticks.assertions import assert_topic_published
```

| ROS2 distro | Python           | Status                   |
| ----------- | ---------------- | ------------------------ |
| Humble      | 3.10, 3.11       | supported                |
| Iron        | 3.10, 3.11       | supported                |
| Rolling     | 3.10, 3.11, 3.12 | supported                |
| (none)      | 3.10–3.13        | decorators + plugin only |

## Releases and stability

* **0.x** = pre-1.0, expect minor breaking changes between minors.
* **1.0** locks the wire contract and the decorator signatures.
* **Schema versions** are independent of SDK versions; see [Wire contract](/sdk/wire-contract).

## Links

<CardGroup cols={2}>
  <Card title="Install" icon="download" href="/sdk/installation">
    `pip install roboticks` + ament\_cmake setup.
  </Card>

  <Card title="Decorators" icon="at" href="/sdk/decorators">
    `@confirms`, `@tags`, `@deadline`, `@requires_sim`.
  </Card>

  <Card title="Assertions" icon="check-double" href="/sdk/assertions">
    rclpy-aware wait-and-assert helpers.
  </Card>

  <Card title="Wire contract" icon="file-code" href="/sdk/wire-contract">
    Authoritative schema reference.
  </Card>
</CardGroup>
