# description
JSON Schema for the YAML frontmatter block of a ROBOT.md file.

# properties.rcan_version.description
RCAN protocol version. Must be 3.0 or higher (ecosystem policy: RCAN 3.0+ only going forward; 2.x no longer accepted).

# properties.schema.description
Optional self-reference to the JSON schema this file conforms to.

# properties.metadata.properties.rcn_ids.description
Robot Component Numbers identifying this robot's constituent components (sensors, actuators, SBC, etc.) as registered on RRF /v2/components. Ships v0.9.6 alongside RMN/RHN for the v1.0.0 compliance declaration.

# properties.metadata.properties.rmn.description
Robot Model Number — RRF-registered identity of the underlying platform model (e.g. the reference SKU from which this instance was built).

# properties.metadata.properties.rhn_ids.description
Robot Harness Numbers identifying tested harness/cabling configurations this robot conforms to, as registered on RRF /v2/harnesses.

# properties.physics.properties.kinematics.items.properties.length_mm.description
Legacy scalar — fallback for `a_mm` when DH params aren't declared. Treated as the horizontal offset from this joint to the next.

# properties.physics.properties.kinematics.items.properties.a_mm.description
DH parameter: distance from this joint's axis to the next joint's axis along the local +x direction (perpendicular to this joint's rotation axis).

# properties.physics.properties.kinematics.items.properties.d_mm.description
DH parameter: distance from this joint's axis to the next joint's axis along this joint's rotation axis. For a vertical shoulder_pan riser, d_mm is the vertical height to the shoulder_lift joint.

# properties.physics.properties.kinematics.items.properties.servo_id.description
Bus address of the servo driving this joint. Maps joint to the corresponding driver entry. Set by `robot-md autodetect` from the driver config.

# properties.physics.properties.kinematics.items.properties.encoder_sign.description
+1 if positive encoder delta ⇒ positive joint-angle delta; -1 if the encoder is reversed relative to the kinematic convention. Populated by `robot-md calibrate --sign` after observing one test move per joint.

# properties.physics.properties.kinematics.items.properties.zero_pose_steps.description
Encoder reading when this joint is at 0° in the kinematic convention. Recorded by `robot-md calibrate --zero` while the operator holds the arm in its declared zero pose.

# properties.physics.properties.poses.description
Named joint-space poses. 'ready' is the manipulation home if present.

# properties.physics.properties.workspace.description
Reachable envelope, relative to a named pose.

# properties.physics.properties.solver.description
Baseline IK metadata — enough for a planner to compute forward/inverse kinematics from ROBOT.md alone, without an external URDF. Populated by `robot-md autodetect` (deterministic fields) + `robot-md calibrate` (physical fields).

# properties.physics.properties.solver.properties.convention.description
Kinematic convention used by the `kinematics[]` array. `DH` = modified Denavit-Hartenberg (axis + length_mm per joint). `URDF` = reference an external URDF file via `extensions.urdf_ref`. `custom` = body prose must describe the convention.

# properties.physics.properties.solver.properties.base_frame.description
World-frame convention for the arm base.

# properties.physics.properties.solver.properties.encoder.properties.steps_per_rev.description
Encoder steps per full revolution (360°). Default for the arm. Autodetect fills this from driver type (Feetech STS3215 = 4096, Dynamixel XM430 = 4096, etc).

# properties.physics.properties.solver.properties.camera.description
Camera mount relationship to the kinematic chain — needed to project image pixels into the arm's frame.

# properties.physics.properties.solver.properties.camera.properties.mount.description
Where the camera is mounted. `world` = fixed frame (eye-to-hand). `tool0` = end-effector (eye-in-hand). `link_<id>` = a specific intermediate link.

# properties.physics.properties.solver.properties.camera.properties.extrinsic.description
6-DoF transform from the mount frame to the camera frame: [tx, ty, tz, rx, ry, rz] in mm and radians. Null if calibration is required at runtime.

# properties.physics.properties.solver.properties.gripper.description
Gripper geometry + actuation calibration. Needed so a planner can compute where the tip lands given a wrist pose.

# properties.physics.properties.solver.properties.gripper.properties.joint_id.description
Which entry in `kinematics[]` is the gripper (end-effector).

# properties.physics.properties.solver.properties.gripper.properties.tip_offset_mm.description
[x, y, z] offset from the gripper's link frame to the grasp point, in mm.

# properties.physics.properties.solver.properties.gripper.properties.open_steps.description
Encoder target for the gripper-open pose.

# properties.physics.properties.solver.properties.gripper.properties.close_steps.description
Encoder target for the gripper-close pose.

# properties.physics.properties.solver.properties.cameras.items.properties.extrinsic_source.description
Provenance of extrinsic. `preset_default`: shipped guess. `hand_eye_calibrated`: legacy hand-eye. `gripper_silhouette_calibrated`: from `robot-md calibrate --extrinsic`. `user_declared`: edited by hand.

# properties.physics.properties.solver.properties.cameras.items.properties.extrinsic_residual_mm.description
Mean residual (mm) from the last calibration; written by calibrate --extrinsic.

# properties.vision.description
Perception vocabulary — objects the robot knows how to see.

# properties.drivers.items.properties.backend.description
Optional entry-point name forcing a specific CapabilityBackend for this driver.

# properties.safety.properties.max_joint_velocity_dps.description
Sanity bound: 36000 dps = 100 RPS. Physically absurd values above this are rejected at validation time so a malformed or hostile manifest can't declare 'unlimited' and slip past the planner.

# properties.safety.properties.max_linear_velocity_ms.description
Sanity bound: 100 m/s = 360 km/h. Anything faster is not a robot.

# properties.safety.properties.payload_kg.description
Sanity bound: 10000 kg. Anything heavier is industrial/construction class — use a vertical-specific spec rather than ROBOT.md v1.

# properties.safety.properties.workspace_bounds_m.description
Optional [x, y, z] workspace envelope in meters. Planner must not command beyond these bounds.

# properties.safety.properties.failsafe_behavior.description
What the robot does when control comms are lost. 'stop' is safest for most physical systems; 'hold' preserves position for stateful tasks; 'home' returns to a declared safe pose; 'custom' requires explicit prose in the body.

# properties.safety.properties.estop.properties.response_ms.description
Bound tightened to 5000 ms (was 10000). A responsible robot E-stop should complete in well under 1 second; 5s is the outer envelope, anything higher is suspect.

# properties.compliance.properties.annex_iii_basis.description
EU AI Act Annex III use-case basis per rcan-spec §22. When set, compliance.fria_ref MUST be a non-null URI (FRIA gate, enforced since v0.9.2).

# properties.compliance.allOf[].description
v0.9.2 FRIA gate per rcan-spec §22: declaring annex_iii_basis commits the operator to a Fundamental Rights Impact Assessment, so fria_ref must be present and a non-null absolute URI. Pattern enforces an RFC 3986 scheme + colon + non-empty path/authority — portable across jsonschema installs that do or don't have rfc3987 format extras.

# properties.learned_skills.description
Append-only skill catalogue — what the robot has empirically demonstrated.

# properties.spatial-eval.description
SP6 spatial intelligence eval declaration. Phase 0 ships a fixed v1 stack: Anthropic-only reasoning on both tracks, fixed unit roster (O1/O2/O3/A1/A2). Future protocol revisions widen these constraints.