Skip to content

feat: two-layer architecture — core primitives + engine runtime#32

Open
prakashUXtech wants to merge 1 commit intomainfrom
feat/two-layer-architecture
Open

feat: two-layer architecture — core primitives + engine runtime#32
prakashUXtech wants to merge 1 commit intomainfrom
feat/two-layer-architecture

Conversation

@prakashUXtech
Copy link
Contributor

Summary

Splits soul-protocol into two clean layers within the same repo:

  • core/ — Protocol primitives (Identity, MemoryStore, MemoryEntry, SoulContainer, .soul file format, Manifest). Depends only on pydantic. This is the portable standard — like the MP3 spec.
  • engine/ — Opinionated runtime namespace re-exporting existing modules (Soul, CognitiveEngine, MemoryManager, OCEAN personality, psychology-informed memory). This is the player that brings souls alive.

What changed

  • New src/soul_protocol/core/ — 6 files, ~480 lines of schema-free primitives
  • New src/soul_protocol/engine/ — 4 files, thin re-export layer over existing modules
  • pyproject.toml — Core deps trimmed to pydantic>=2.0 only. Runtime deps moved to [engine] extra. Added [all] composite extra.
  • __init__.py — Added core primitive exports (CoreIdentity, CoreManifest, CoreMemoryEntry, DictMemoryStore, MemoryStore). All existing exports preserved.
  • 41 new tests in tests/test_core/ covering all core primitives

Install paths

pip install soul-protocol          # core only — pydantic, nothing else
pip install soul-protocol[engine]  # full runtime — yaml, click, rich, crypto
pip install soul-protocol[all]     # everything including MCP, graph, vector

Zero breakage

All existing imports (from soul_protocol import Soul) work unchanged.

Test plan

  • 519 unit tests pass
  • 28 E2E integration tests pass
  • 224 simulation checks pass (32 scenarios, 4091 interactions)
  • 36 real-user simulation checks pass (6 scenarios)
  • 41 new core tests pass
  • All existing imports verified backward-compatible

Introduce a clean separation between protocol primitives (core/) and the
opinionated runtime (engine/). The core layer depends only on pydantic
and provides: Identity, MemoryEntry, MemoryStore protocol, DictMemoryStore,
SoulContainer, .soul file pack/unpack, and Manifest.

The engine layer re-exports existing modules (Soul, CognitiveEngine,
MemoryManager, etc.) under a structured namespace.

Packaging: `pip install soul-protocol` now only requires pydantic.
Full runtime available via `pip install soul-protocol[engine]`.
All existing imports preserved for backward compatibility.

41 new core tests. All 519 existing tests, 28 E2E tests, and 260
simulation checks pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

Issues (must fix)

  • No linked issue found. PRs should reference an issue (Fixes #123).

Heads up

  • Large PR detected (1169 lines across 18 files). Consider splitting into smaller PRs.
  • This PR touches sensitive files (project dependencies). These paths require maintainer review via CODEOWNERS.
  • Dependency files changed: pyproject.toml (+10/-3). Reviewers: check for added/removed/changed packages.

Please update your PR to address these points.

@prakashUXtech
Copy link
Contributor Author

Self-Review: PR #32 — Two-Layer Architecture

What's Good

  • Core/engine boundary is clean — core/ has zero imports from engine modules
  • Core primitives (Identity, MemoryStore, MemoryEntry, SoulContainer, .soul file, Manifest) are schema-free and pydantic-only
  • Engine is a thin re-export namespace over existing root-level modules — zero code duplication
  • 41 new core tests, all passing
  • pyproject.toml correctly splits deps: core = pydantic only, [engine] extra = yaml/click/rich/crypto
  • All 519 existing tests + 28 E2E + simulations pass — zero regressions

Issues Found

  1. datetime.now() without timezonecore/identity.py, core/memory.py, core/manifest.py all use datetime.now() which creates naive datetimes. Should use datetime.now(tz=timezone.utc) for portability. Non-blocking but worth fixing.

  2. core/__init__.py missing SoulContainer in __all__ — Verify the __all__ list includes all public exports.

  3. DictMemoryStore.search() token overlap is basic — Fine for the reference implementation, but worth a docstring noting this is intentional and production users should plug in a real search strategy.

  4. unpack_to_container returns DictMemoryStore — Hardcodes the reference implementation. Consider making the store type configurable via a factory parameter.

  5. Engine __init__.py re-exports could break if source modules move — The thin aliases work but are fragile. A test that verifies all engine exports resolve would catch regressions.

Verdict

Approve with minor suggestions. The separation is clean and well-tested. The core is exactly the right size (~480 lines) for a future Go port.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant