Phase 3a of the solver server integration: add dict/JSON serialization
to all KCSolve pybind11 types so SolveContext and SolveResult can be
transported as JSON between the Create client, Silo server, and solver
runners.
Implementation:
- Constexpr enum string mapping tables for all 5 enums (BaseJointKind,
SolveStatus, DiagnosticKind, MotionKind, LimitKind) with template
bidirectional lookup helpers
- File-local to_dict/from_dict conversion functions for all 10 types
(Transform, Part, Constraint::Limit, Constraint, MotionDef,
SimulationParams, SolveContext, ConstraintDiagnostic,
SolveResult::PartResult, SolveResult)
- .def("to_dict") and .def_static("from_dict") on every py::class_<>
binding chain
Serialization details per SOLVER.md §3:
- SolveContext.to_dict() includes api_version field
- SolveContext.from_dict() validates api_version, raises ValueError on
mismatch
- Enums serialize as strings matching pybind11 .value() names
- Transform: {position: [x,y,z], quaternion: [w,x,y,z]}
- Optional simulation serializes as None/null
- Pure pybind11 py::dict construction, no new dependencies
Tests: 16 new tests in TestKCSolveSerialization covering round-trips for
all types, all 24 BaseJointKind values, all 4 SolveStatus values,
json.dumps/loads stdlib round-trip, and error cases (missing key,
invalid enum, bad array length, wrong api_version).
Add the kcsolve pybind11 module exposing the KCSolve C++ API to Python:
- PyIKCSolver trampoline enabling Python IKCSolver subclasses
- Bindings for all 5 enums, 10 structs, IKCSolver, and OndselAdapter
- Module functions wrapping SolverRegistry (available, load, joints_for,
set_default, get_default, register_solver)
- PySolverHolder class forwarding virtual calls with GIL acquisition
- register_solver() for runtime Python solver registration
IKCSolver constructor moved from protected to public for pybind11
trampoline access (class remains abstract via 3 pure virtuals).
Includes 16 Python tests covering module import, type bindings, enum
values, registry functions, Python solver subclassing, and full
register/load/solve round-trip.
Closes#288