Skip to content

Implement Pluggable Serialization Layer (Phase 3) #55

Description

@biosynthart

Goal

Create the pluggable serialization infrastructure for effects. JSON is the default (WebSocket-compatible), with stubs for msgpack and protobuf for future performance needs.

Files to Create/Modify

  • ecosim/serialization/__init__.py (NEW) — SerializerRegistry export
  • ecosim/serialization/interface.py (NEW) — Serializer ABC + SerializerRegistry
  • ecosim/serialization/json_serializer.py (NEW) — JsonSerializer implementation

Deliverables

1. Serializer ABC (interface.py)

class Serializer(ABC):
    @abstractmethod
    def serialize(self, effect: Effect) -> bytes | str: ...

    @abstractmethod
    def deserialize(self, data: bytes | str) -> Effect: ...

    @abstractmethod
    def serialize_batch(self, effects: list[Effect]) -> bytes | str: ...

    @abstractmethod
    def deserialize_batch(self, data: bytes | str) -> list[Effect]: ...

class SerializerRegistry:
    def register(self, name: str, serializer: Serializer) -> None
    def get_default(self) -> Serializer
    def get(self, name: str) -> Serializer

2. JsonSerializer (json_serializer.py)

Default implementation using Effect.to_dict(). Compatible with existing WebSocket protocol and browser-based replay tools.

3. EffectLog Class (effects.py — add to existing file)

Append-only log of all effects for deterministic replay:

class EffectLog:
    def append(self, tick: int, effects: list[Effect]) -> None
    def get_tick_effects(self, tick: int) -> list[Effect] | None
    def serialize_log(self, start_tick: int = 0, end_tick: int | None = None) -> bytes | str

4. Engine Integration

Engine holds a reference to the serializer registry and uses it for effect logging:

class EcosystemEngine:
    def __init__(self):
        self.serializer_registry = SerializerRegistry()
        self.serializer_registry.register("json", JsonSerializer())
        self.effect_log = EffectLog(serializer=self.serializer_registry.get_default())

    def step(self, dt=0.1):
        ...
        # After applying effects:
        self.effect_log.append(self.tick, all_effects)

Unit Tests Required (tests/test_serialization.py)

  1. test_json_serializer_roundtrip_single_effect — Serialize StateVarDelta → deserialize → verify equality
  2. test_json_serializer_roundtrip_batch — Serialize list of effects → deserialize → verify all match
  3. test_serializer_registry_registers_and_retrieves — Register "json" and "msgpack", retrieve by name
  4. test_effect_log_appends_and_retrieves_by_tick — Append effects for ticks 1-10, retrieve tick 5
  5. test_effect_log_serializes_to_json_string — serialize_log() returns valid JSON string

Verification Criteria

  • JsonSerializer produces output identical to current WebSocket packet format (for events)
  • SerializerRegistry allows easy addition of msgpack/protobuf implementations later
  • EffectLog can serialize a full tick's effects and deserialize them back without loss

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions