Day-to-day work with the NobroRTOS SDK: the mental model, the declarative app generator, the prebuilt-firmware loop, authoring C modules against the prebuilt runtime, and keeping a working tree clean.
This manual helps a firmware developer understand the repository, run local validation, and assemble a small NobroRTOS application.
NobroRTOS is organized around explicit contracts:
- A board describes memory layout, critical pins, and capacity budgets.
- A manifest describes modules, required capabilities, owned capabilities, memory budgets, deadline contracts, and fault thresholds.
- The admission controller validates the manifest before runtime work begins.
- The runtime owns mailbox IPC, alarms, key-value configuration, quotas, degraded-mode state, and recovery coordination.
- SAL traits keep applications independent from concrete drivers.
- Host reports make boot, admission, runtime, health, and recovery state readable from outside the firmware image.
Install Rust and the embedded target:
rustup target add thumbv7em-none-eabihfUse _work/ for generated files:
$env:CARGO_TARGET_DIR = (Resolve-Path '_work').Path + '\cargo-target'Run commands from core/ unless noted otherwise:
cd core
cargo test -p nobro-kernel --target x86_64-pc-windows-msvc
cargo test -p nobro-sal --target x86_64-pc-windows-msvc
cargo test -p nobro-host --target x86_64-pc-windows-msvccargo check --workspace uses core/.cargo/config.toml, so the default build
target is thumbv7em-none-eabihf.
Board layout is selected by feature:
| Feature | App origin | Use |
|---|---|---|
board-promicro-nosd |
0x1000 |
ProMicro-style nRF52840 images without SoftDevice |
board-nicenano-s140 |
0x26000 |
nRF52840 images that coexist with SoftDevice S140 v6 layout |
Example:
cargo check -p sal-adapter-demo --no-default-features --features board-promicro-nosdA NobroRTOS application should assemble existing contracts rather than hide hardware behavior in private globals.
- Select one board feature.
- Build adapter descriptors for each enabled device.
- Assemble a
SystemManifestwith module budgets and capabilities. - Build a
StartupGraph. - Call
AdmissionController::admit. - Construct
Runtimefrom the admitted plan. - Export host reports for diagnostics.
For small apps, BootAssembly can do steps 3 through 6 while keeping the
manifest, startup graph, admission result, and runtime visible:
use nobro_kernel::{
kernel_module_spec, BootAssembly, Capability, CapabilitySet, Criticality,
DeadlineContract, FaultThresholds, MemoryBudget, ModuleId, ModuleSpec,
StartupDependency, SystemProfile,
};
type AppBoot = BootAssembly<4, 4, 4, 4, 4, 4, 4, 4, 16>;
let specs = [
kernel_module_spec(
MemoryBudget::new(16 * 1024, 4 * 1024, 4),
DeadlineContract::new(20_000, 10),
),
ModuleSpec::new(ModuleId::Sensor, Criticality::Driver)
.requires(CapabilitySet::empty().with(Capability::SamplePool))
.memory(MemoryBudget::new(8 * 1024, 2 * 1024, 2)),
];
let boot = AppBoot::build(
&specs,
&[StartupDependency::new(ModuleId::Sensor, ModuleId::Kernel)],
SystemProfile::new(64 * 1024, 16 * 1024, 8, 4),
FaultThresholds::DEFAULT,
0,
)?;
assert!(boot.manifest_report.verify_checksum());
assert!(boot.admission_report.verify_checksum());Firmware that depends on nobro-hal can enable nobro-kernel/hal-profile and
derive the profile from the active board package:
let profile = SystemProfile::from_board_package(&nobro_hal::ACTIVE_BOARD_PACKAGE)?;For diagnostics-first startup code, use build_with_failure and export the
reports from the returned BootAssemblyFailure before halting or entering a
maintenance path:
let failure = match AppBoot::build_with_failure(
&specs,
&[StartupDependency::new(ModuleId::Sensor, ModuleId::Kernel)],
SystemProfile::new(64 * 1024, 16 * 1024, 8, 4),
FaultThresholds::DEFAULT,
0,
) {
Ok(_) => unreachable!(),
Err(failure) => failure,
};
assert!(failure.manifest_report.verify_checksum());Both successful assemblies and BootAssemblyFailure expose reports(), so
firmware can publish the manifest and admission reports through one helper.
An application can assemble the manifest, startup graph, admission plan, and runtime
through BootAssembly, then publish adapter compatibility before entering
hardware-facing code.
Application code should depend on nobro-sal traits:
BusSalfor I2C, SPI, and UART-like bus accessStreamSalfor framed byte streamsRadioSalfor radio process loops and packet movementActuatorSalfor deadline-aware actuator outputSensorSalfor sampled sensor dataCryptoSalfor cryptographic operationsAiInferenceSalfor bounded on-device, sidecar, hybrid, or remote inference
Adapters translate concrete hardware or libraries into those traits. Apps should not call vendor headers directly.
For bring-up and CI, nobro-adapter-sensor-stub can run as a deterministic
sensor fixture. It can emit plausible IMU samples, stay silent, inject periodic
adapter errors, or produce implausible payloads without requiring external
hardware.
AI modules should declare their model identity, backend kind, memory budget, input/output bounds, timeout, and recovery behavior before admission. Local TinyML, generated C++ model libraries, accelerator sidecars, companion computers, and third-party API calls should all enter the system as adapters rather than private schedulers.
ROS and micro-ROS compatibility should be implemented as bridge adapters. Topic-like data should use bounded queues, service-like calls should use fixed request/response records, action-like work should expose bounded goal, feedback, and result state, and parameters should map to fixed-capacity configuration.
For low-power mesh interop, the host contracts decode IEEE 802.15.4 MAC frames and classify Thread-style 6LoWPAN payloads. A gateway adapter can retain the base MAC record and add a bounded Thread rollup when a captured PSDU contains IPHC or IPv6 6LoWPAN traffic.
AI model contracts and ROS bridge contracts can be exported as fixed reports, so host tools can inspect model memory, timeout, stale-result policy, bridge entity counts, total buffer demand, and transport choice without running a hardware probe.
Camera adapters should keep scene/liveness analytics and person detection separate:
liveness proves the camera stream is real, while the optional person model turns
the latest frame into a bounded inference result. Multi-board manifests can pass
the same file with the person_model key on a vision node.
Audio adapters can stream little-endian PCM16 through a bounded marker protocol. The keyword-spotting feature contract is fixed at 16 kHz mono, one second, 15 frames, and 8 log-energy bands, so a PDM or I2S adapter only has to supply bounded PCM windows.
NobroRTOS exports fixed-layout reports with NOBRO_* symbols. The canonical
contract is host/nobro-host-contract.json.
Important reports:
NOBRO_BOARD_PROFILE_REPORTNOBRO_BOARD_PACKAGE_REPORTNOBRO_MANIFEST_REPORTNOBRO_ADAPTER_COMPAT_REPORTNOBRO_AI_MODEL_REPORTNOBRO_ROS_BRIDGE_REPORTNOBRO_ADMISSION_REPORTNOBRO_RUNTIME_REPORTNOBRO_HEALTH_REPORTNOBRO_EVENT_LOG_REPORTNOBRO_MODULE_RUNTIME_REPORTNOBRO_DEGRADE_APPLICATION_REPORT
Reports are designed to be copied from memory as repr(C) records and checked
with simple XOR checksums.
Host-side simulators mirror selected runtime contracts for early design and CI checks:
python tools/nobro_contract_tool.py sample-sensor --mode bad_data_every --ticks 4 --period 1
python tools/nobro_contract_tool.py check-ai-route
python tools/nobro_contract_tool.py check-ai-route-matrix
python tools/nobro_contract_tool.py check-ai-preflight-matrix
python tools/nobro_contract_tool.py check-ros-preflight-matrix
python tools/nobro_contract_tool.py check-bundle-matrix
python tools/nobro_contract_tool.py sample-recovery --error sensor_read_fail --events 4
python tools/nobro_contract_tool.py check-recovery-matrix
python tools/nobro_contract_tool.py sample-watchdog --timeout-us 100 --sweeps 3 --step-us 75
python tools/nobro_contract_tool.py check-watchdog-matrix
python tools/nobro_contract_tool.py sample-scheduler --ticks 1000 21020 41050 --tolerance-us 25
python tools/nobro_contract_tool.py check-scheduler-matrix
python tools/nobro_contract_tool.py sample-event-log --capacity 3 --events 4 --recent 3
python tools/nobro_contract_tool.py check-event-log-matrix
python tools/nobro_contract_tool.py sample-quota
python tools/nobro_contract_tool.py check-quota-matrix
python tools/nobro_contract_tool.py sample-degrade --flash-limit 73728 --ram-limit 16384
python tools/nobro_contract_tool.py check-degrade-matrix
python tools/nobro_contract_tool.py sample-runtime-drill --fault-count 3
python tools/nobro_contract_tool.py check-runtime-drill --fault-count 3
python tools/nobro_contract_tool.py check-software-surface
python tools/nobro_contract_tool.py check-python-surface
python tools/nobro_contract_tool.py check-cli-command-surface
python tools/nobro_contract_tool.py check-starter-templates
python tools/nobro_contract_tool.py sample-startup
python tools/nobro_contract_tool.py check-startup-matrix
python tools/nobro_contract_tool.py check-boot-summary-matrix
python tools/nobro_contract_tool.py sample-project platformio --name edge_demo --module control
python tools/nobro_contract_tool.py sample-project python_board_bridge --name edge_demo --module control
python tools/nobro_contract_tool.py write-project platformio --output _work\edge_demo --name edge_demo
python tools/nobro_contract_tool.py check-project _work\edge_demo --target platformio
python tools/nobro_contract_tool.py repair-project _work\edge_demo --target platformio
python tools/verify_timing_lease.py
python tools/tutorial_runner.pyGenerated starter projects include VS Code task metadata for the same project
check, so IDE users can run the validation gate from the command palette.
The project check command returns non-zero when validation fails, which makes
the generated task suitable for CI and editor problem workflows.
repair-project can rebuild that IDE metadata without overwriting project code
or nobro-contract.json.
Project checks validate the expected task commands, not just task labels, so
renamed or stale editor tasks are reported before they mislead a workflow.
tools/static_budget.py can gate build-time memory and timing envelopes for an
ELF before it is packaged. It reports flash, static RAM, worst-case stack, and a
static instruction-cycle estimate, then returns non-zero when a configured RAM
or cycle budget is exceeded:
python tools/static_budget.py _work\firmware\app.elf --ram-budget 32768
python tools/static_budget.py _work\firmware\app.elf --cycle-budget 200000 --clock-hz 64000000The timing estimate is a build-time review gate, not a substitute for final
target timing validation. It flags loops, recursion, indirect calls, and
unknown mnemonics so deadline-sensitive modules can be inspected before they
reach board-specific tests.
The static web flasher lives under packages/web-flasher and supports local
firmware drop, Web Serial boot-entry commands, and WebUSB transfers for devices
that expose a compatible bulk endpoint.
The static block editor lives under packages/block-editor and emits the same
app.json schema consumed by tools/nobro_app.py, so visual workflows still
land in the normal contract validator and Rust skeleton generator.
check-starter-templates validates every starter target in a temporary
directory, which keeps Arduino, PlatformIO, standalone SDK, Python host, and
Python board bridge onboarding paths aligned.
Python host starter projects include runtime drill, AI route, AI route matrix,
AI preflight matrix, ROS preflight matrix, recovery matrix, watchdog matrix,
scheduler matrix, event log matrix, quota matrix, degrade matrix, startup matrix, boot summary matrix,
bundle matrix, and report matrix gate tasks.
Python board bridge templates also include an offline bridge smoke task for
MicroPython, CircuitPython, and mPython-style status-line workflows.
The runtime drill output includes a recovery summary with retry, notification,
reboot, final-state, and self-healing flags for software-only review.
The runtime drill checker turns the same scenario into a pass/fail software
gate for CI and VS Code tasks. The software surface checker combines host
contract, package metadata, public headers, Python public surface, CLI command
surface, starter templates, AI route matrix, AI preflight matrix, ROS preflight matrix, recovery
matrix, watchdog matrix, scheduler matrix, event log matrix, quota matrix,
degrade matrix, startup matrix, boot summary matrix,
bundle matrix, report matrix, and runtime drill validation before packaging.
The timing and lease verifier exhaustively checks a bounded lease state space
and scheduler-jitter model without external model-checker dependencies.
The tutorial runner validates the public NobroRTOS book, tutorial app contract,
generated skeleton path, and bounded verifier in one beginner-friendly gate.
Fleet OTA rollout logic lives in nobro-net: use FleetOtaOrchestrator to
stage canary-first update waves, enforce maximum parallel updates, block rollout
when fleet health is low, and roll failed nodes back before a transport-specific
OTA sender moves chunks through the mesh.
The Python public surface checker validates the top-level package exports with
AST parsing, so host tools can catch stale imports without executing package
initialization.
The CLI command surface checker validates command registration and README
coverage together, so onboarding instructions fail early when a command name
drifts.
The report matrix checker verifies fixed-report status classes, checksum
handling, error labels, and decoded runtime, AI model, and ROS bridge fields.
The AI route checker validates route-policy behavior without contacting a
remote inference endpoint. It can model on-device, edge-sidecar, remote API,
and hybrid route decisions by changing backend, readiness, budget, stale-age,
and endpoint-failure arguments. The AI route matrix checker validates local,
remote API, edge sidecar, stale snapshot, degraded fallback, and unavailable
paths in one gate.
The AI preflight matrix checker validates inference-call admission before a
model runs: input/output buffers, scratch and arena RAM, non-zero local arena
declarations, module capability declarations, route budget, stale snapshot
limits, degraded fallback, unavailable routes, and endpoint circuit state.
The ROS preflight matrix checker validates bridge-call admission before a ROS
transport or agent is contacted: topic payload bounds, service/action response
capacity, queue depth, parameter value size, and timeout budget.
The recovery matrix checker validates ignore, retry, notify, reboot, OK-reset,
fixed-plan execution, dependency-impact reboot planning, runtime state
bookkeeping, and output-buffer backpressure paths in one gate.
The watchdog matrix checker validates non-mutating liveness prechecks, expiry
mutation, heartbeat reset, multi-module expiry, and capacity errors.
The scheduler matrix checker validates on-time ticks, tolerated early/late
jitter, missed deadlines, 32-bit time wraparound, counter reset, and invalid
scheduler configuration.
The event log matrix checker validates fixed-ring capacity accounting,
overwrite pressure, recent-record order, severity thresholds, zero-capacity
drop accounting, and invalid input handling.
The quota matrix checker validates fixed-capacity registration, reserve,
release, total-use, strict module identity, limit enforcement, underflow, and
overflow paths.
The degrade matrix checker validates flash, RAM, pool, module-limit,
same-criticality, planner-capacity, and essential-module pressure paths.
The startup sample prints the dependency order for a reference runtime module
set, which helps keep boot sequencing explicit before adding board-specific
adapter code. The startup matrix checker validates no-dependency, chain,
fan-in/fan-out, dependency-impact, unknown-node, self-cycle, duplicate-edge,
and cycle paths for the same deterministic planner. Rust startup graphs can also report the
transitive impact of a faulted dependency in reverse startup order, which gives
recovery code a stable quiesce-before-restart list.
The boot summary matrix checker validates all-pass, missing-stage,
corrupt-checksum, failed-adapter, in-progress-stage, diagnostic-code, and
status-count paths for host-side boot report review.
The bundle matrix checker validates module naming, capability ownership,
AI/ROS descriptor uniqueness, hard-realtime deadlines, startup dependency
errors, and JSON roundtrip stability.
Keep generated data under _work/:
Remove-Item -Recurse -Force _work\cargo-target -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force _work\artifacts -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force _work\logs -ErrorAction SilentlyContinue_work/, target directories, firmware binaries, coverage output, and local
toolchains are ignored by Git.
For the newer graph-oriented flow, use the SDK project command:
python sdk/cli/nobro.py project new rover
python sdk/cli/nobro.py project explain _work/projects/rover/workload.json
python sdk/cli/nobro.py project build _work/projects/rover
python sdk/cli/nobro.py project simulate _work/projects/roverThe concise workload.json task/channel graph regenerates the build input and is
expanded into the same low-level contract the kernel admits. project run combines
contract explanation, build, simulation, and report decoding.
If the desired output is production nRF firmware rather than a host scaffold, use one
short app.nobro declaration:
python sdk/cli/nobro.py firmware tutorials/rover-one-file/app.nobro --build
python sdk/cli/nobro.py project explain _work/projects/rover/workload.jsonThe generator emits workload.json, generation.json, and a compiling no_std Cargo
crate from the same input. The explicit board profile selects the S140 or no-SoftDevice
memory layout. Defaults reduce beginner boilerplate while keeping budget review visible.
If the exact board/composition has a measured compare-wake-to-dispatch upper bound,
place wake 25us directly after the board line. It is charged by admission; omit
the line rather than inventing a value when no bound has been measured.
gen-app turns a declarative module spec into a buildable NobroRTOS firmware app.
You describe the module (criticality + memory budget); the generator emits a workspace
crate whose main.rs assembles the manifest via BootAssembly, admits it, and exports
the host-readable NOBRO_MANIFEST_REPORT / NOBRO_ADMISSION_REPORT. The generated Rust
is compiler-checked, so your contract is preserved - you never hand-write Rust.
This is the declarative app-generation path: describe the app as data, generate the Rust.
python tools/nobro_contract_tool.py gen-app --name my_control_app --module control
# options: --criticality {best_effort|user|driver|system} --flash <bytes> --ram <bytes> --pool <slots>This writes core/apps/control/my_control_app/ (Cargo.toml, build.rs, src/main.rs,
nobro-contract.json, README.md) and registers it as a workspace member.
cd core
cargo build -p my-control-app --releaseFlash and read the reports (see GETTING_STARTED.md). A booted
app populates NOBRO_MANIFEST_REPORT (magic NBMF) and NOBRO_ADMISSION_REPORT
(magic NBAD); both carry the module count and a sealed checksum, so a host tool
confirms the manifest assembled and admission passed without a defmt decoder.
Verified end to end on the development board: a generated driver-criticality app compiles for
thumbv7em, boots, assembles a 2-module manifest (kernel + your module), and passes
admission.
Edit nobro-contract.json (the module's criticality / memory budget) and re-run
gen-app --overwrite, or edit src/main.rs directly. Either way the manifest is
re-validated by the compiler and at admission.
gen-app scaffolds a Rust app. To write module logic outside Rust, generate a
C or C++ module skeleton over the C ABI:
python tools/nobro_contract_tool.py gen-module --name my_sensor --lang c --out my_mod
python tools/nobro_contract_tool.py gen-module --name my_sensor --lang cpp --out my_modThis writes an editable module (nobro_app_init() once, nobro_app_poll() each
cycle) and prints the build command, which compiles + links your file into the
c_abi_demo firmware via the c-source / cpp-source path (needs
arm-none-eabi-gcc / g++). Both languages are verified end to end on the development board - the
kernel admits the C or C++ module and it drives a sensor to a passing report. See
bindings/c/README.md and
bindings/cpp/README.md.
UX rung 0 target: flash a prebuilt UF2 once, then iterate by editing data
(app.json from the block editor) — no toolchain, no rebuild, code-free after first
flash.
1. Drag-drop prebuilt UF2 → board enumerates (DFU/COM)
2. Open block editor → design app visually
3. Export app.json → drop on serial / future UF2 data partition
4. Web console / ReportReader → plain-English PASS/FAIL from NOBRO_* reports
NobroRTOS ships the bundle builder and manifest gate. Runtime app.json hot-swap is not
implemented; changing application behavior still requires rebuilding firmware.
| Piece | Status |
|---|---|
Block editor → app.json |
Implemented |
| Web-flasher report console | Implemented |
nobro_app.py validator |
Done |
| Bootloader-safe UF2 flash | Done (hw_eval --flash uf2) |
| Prebuilt diagnostic UF2 bundle | Implemented by package_prebuilt_uf2.py --build |
app.json runtime reload |
Not implemented; rebuild required |
The shell UF2 is a known-good firmware image that:
- Boots through the six-stage chain and emits decodable
NOBRO_*reports. - Enumerates as USB CDC and exposes host-readable diagnostic reports.
- Bundles validated starter
app.jsonas source input for a later rebuild.
Build command:
python tools/package_prebuilt_uf2.py --buildAfter the one-time UF2 flash:
- Block editor exports
app.json. - User validates the file and rebuilds firmware; live serial/mass-storage ingestion is not currently supported.
- Console shows: "✅ servo mounted, sensor alive" or the first-fault sentence.
This matches the CircuitPython "edit code.py, save, it runs" bar — except the
editable artifact is contract data, not Python source.
python tools/package_prebuilt_uf2.py --check verifies:
- The committed bundle manifest matches the safe flash layout.
- Sample
app.jsonfrom the block editor passesnobro_app.validate(). - A locally built UF2, when present under
_work/prebuilt/, has valid block structure, family ID, and address bounds.
Tier C is for C developers who want NobroRTOS's control plane (admission, budgets,
leases, NOBRO_* reports) without touching the Rust toolchain. You get a prebuilt
libnobro.a containing the whole runtime — boot, vector table, kernel, host services —
and you supply one C file.
No release bundle is currently published. A trusted builder with the Rust toolchain runs:
python tools/build_libnobro.py --build # stages _work/tierc/The bundle: libnobro.a, the linker scripts it expects (link.x, memory.x,
defmt.x), the C ABI headers (nobro_app.h, nobro_rtos.h), a reference module
(imu_module.c), and one-line build scripts.
Your entire authoring surface is two functions against nobro_app.h:
#include "nobro_app.h"
int32_t nobro_app_init(void) {
uint8_t wake[2] = {0x6B, 0x01};
return nobro_i2c_write(0x68, wake, 2); /* bounded host service */
}
int32_t nobro_app_poll(void) {
/* nobro_i2c_write_read(...) + nobro_publish_imu(...) */
return 0;
}The kernel admits your module (capabilities, memory budget, deadlines) and drives
init/poll; hardware is reachable only through the bounded host services.
The shipped runtime owns callback state through ForeignModuleRunner: rejected
admission never reaches nobro_app_init, and a negative init or poll result
revokes all host-service authority before further callbacks are rejected. The
runtime records init/poll failures as structured module recovery faults before
entering its fail-closed platform idle path.
Every exported host service also passes through one dispatcher-owned
ForeignHostContext. The C module cannot provide an identity: the context binds
the admitted module, checks its capability, charges bounded call/byte usage, and
records the attempted and completed operation before returning a result. Quota
exhaustion is reported as a negative host-service result and therefore follows
the same fail-closed callback recovery path.
./build.sh my_module.c # or build.cmd my_module.c on Windows
# = arm-none-eabi-gcc <cpu flags> my_module.c \
# -Wl,--whole-archive libnobro.a -Wl,--no-whole-archive \
# -T link.x -T defmt.x -nostartfiles -lm -o firmware.elf--whole-archive matters: the vector table lives in the archive and nothing
references it by symbol, so the linker must keep every member.
The ELF targets the no-SoftDevice layout (app at 0x1000). Flash it with a compatible
SWD tool (docs/GETTING_STARTED.md) or convert it to UF2 for drag-and-drop. The firmware
seals NOBRO_IMU_HEALTH_REPORT; consume it through a transport exposed by the selected
application. Machine-specific probe scripts and endpoint settings are not distributed.
- One prebuilt layout today: nRF52840, no-SoftDevice. The S140 variant is a rebuild flag away for whoever produces bundles.
- The link test (
python tools/build_libnobro.py --check) runs in CI, so a bundle that stops linking against plain gcc fails the gate before it reaches you.
This guide keeps the repository clean and repeatable during development.
Use _work/ for all generated assets:
| Path | Purpose |
|---|---|
_work/cargo-target/ |
CARGO_TARGET_DIR |
_work/artifacts/ |
local firmware images |
_work/logs/ |
run logs and captured output |
_work/downloads/ |
temporary downloads |
_work/toolchain/ |
optional portable tools |
_work/ is ignored by Git. Do not commit generated firmware, build caches,
coverage data, or downloaded toolchains.
cd core
$env:CARGO_TARGET_DIR = (Resolve-Path '..\_work').Path + '\cargo-target'
cargo fmt --all -- --check
cargo test -p nobro-kernel --target x86_64-pc-windows-msvc
cargo test -p nobro-sal --target x86_64-pc-windows-msvc
cargo test -p nobro-host --target x86_64-pc-windows-msvc
cargo check --workspace
cd ..
python tools/nobro_contract_tool.py doctor
python tools/nobro_contract_tool.py check-host-contract
python tools/nobro_contract_tool.py check-distribution-metadata
python tools/nobro_contract_tool.py check-public-headers
python tools/nobro_contract_tool.py check-software-surface
python tools/nobro_contract_tool.py check-starter-templates
python tools/nobro_contract_tool.py check-ai-route
python tools/nobro_contract_tool.py check-ai-route-matrix
python tools/nobro_contract_tool.py check-ai-preflight-matrix
python tools/nobro_contract_tool.py check-ros-preflight-matrix
python tools/nobro_contract_tool.py check-bundle-matrix
python tools/nobro_contract_tool.py check-report-matrix
python tools/nobro_contract_tool.py check-recovery-matrix
python tools/nobro_contract_tool.py check-watchdog-matrix
python tools/nobro_contract_tool.py check-scheduler-matrix
python tools/nobro_contract_tool.py check-event-log-matrix
python tools/nobro_contract_tool.py check-quota-matrix
python tools/nobro_contract_tool.py check-degrade-matrix
python tools/nobro_contract_tool.py check-startup-matrix
python tools/nobro_contract_tool.py check-boot-summary-matrix
python tools/nobro_contract_tool.py check-report-matrix
python tools/nobro_contract_tool.py check-runtime-drillcheck-report-matrix should pass before packaging any host tooling change that
touches fixed reports, boot diagnostics, AI model descriptors, or ROS bridge
descriptors.
check-ai-preflight-matrix should pass before packaging AI-facing tooling or
starter templates. It catches oversized inference buffers, insufficient module
RAM, missing AI capabilities, stale snapshot policy violations, degraded
fallback, unavailable routes, and open endpoint circuits without contacting a
model or endpoint.
check-ros-preflight-matrix should pass before packaging ROS-style bridge
tooling or starter templates. It catches oversized bridge payloads, undersized
response buffers, zero-depth queues, parameter value overflow, and timeout
budget violations without contacting a ROS transport or agent.
Kernel recovery tests should pass before changing self-healing logic. They
cover fixed-capacity recovery planning, execution cursor progress, overdue-step
visibility, output-buffer backpressure, watchdog escalation, and module
lifecycle recovery completion without contacting external hardware.
- Keep documentation and comments in English.
- Keep local route notes out of Git.
- Keep generated files under ignored paths.
- Commit coherent architecture or feature slices.
- Do not create tags or releases until the project has a formal complete version.
If Python tooling is needed, use any Python 3 environment (a venv is fine):
python3 -m venv .venv && . .venv/bin/activatePython tools should write outputs under _work/.