chore: initialize EverOS 1.0.0

md-first memory extraction framework for AI agents.

Markdown is the single source of truth; SQLite holds state and LanceDB
provides the rebuildable vector + BM25 + scalar index. The codebase follows
a single-direction DDD layering (entrypoints -> service -> memory -> infra,
with component / core / config cross-cutting) enforced by import-linter.

Engineering surface:
- Coding conventions in .claude/rules/ (path-scoped) and workflows in
  .claude/skills/ (/commit, /new-branch, /pr).
- GitHub Actions CI runs make lint + test + integration; pre-commit mirrors
  the gates locally (ruff, hygiene hooks, gitlint commit-msg).
- Commit messages follow Conventional Commits, enforced by gitlint.
- make lint also enforces datetime two-zone discipline and OpenAPI drift.
This commit is contained in:
Elliot Chen
2026-06-05 22:35:51 +08:00
commit 518b8eca85
636 changed files with 160553 additions and 0 deletions

View File

@ -0,0 +1,61 @@
"""``AgentMemoryPipeline.run`` — empty short-circuit + per-cell event emit."""
from __future__ import annotations
from everalgo.types import ChatMessage, MemCell
from everos.memory import IngestResult
from everos.memory.events import AgentPipelineStarted
from everos.memory.extract.pipeline.agent_memory import AgentMemoryPipeline
class _FakeEngine:
"""Captures emitted events; mirrors ``OfflineEngine.emit`` async signature."""
def __init__(self) -> None:
self.events: list[AgentPipelineStarted] = []
async def emit(self, event: AgentPipelineStarted) -> None:
self.events.append(event)
def _make_cell(n_items: int, ts: int = 1_700_000_000_000) -> MemCell:
items = [
ChatMessage(
id=f"m{i}",
role="user",
sender_id="u1",
sender_name="u",
content="hi",
timestamp=ts,
)
for i in range(n_items)
]
return MemCell(items=items, timestamp=ts)
async def test_empty_cells_short_circuit() -> None:
engine = _FakeEngine()
pipeline = AgentMemoryPipeline(engine) # type: ignore[arg-type]
ingested = IngestResult(session_id="s1", messages=[])
out = await pipeline.run(ingested, cells=[], memcell_ids=[])
assert out.track == "agent_memory"
assert out.status == "accumulated"
assert out.message_count == 0
assert engine.events == []
async def test_emits_one_event_per_cell() -> None:
engine = _FakeEngine()
pipeline = AgentMemoryPipeline(engine) # type: ignore[arg-type]
ingested = IngestResult(session_id="s1", messages=[])
cells = [_make_cell(n_items=2), _make_cell(n_items=3)]
memcell_ids = ["mc_a", "mc_b"]
out = await pipeline.run(ingested, cells=cells, memcell_ids=memcell_ids)
assert out.track == "agent_memory"
assert out.status == "extracted"
assert out.message_count == 5 # 2 + 3
assert [e.memcell_id for e in engine.events] == ["mc_a", "mc_b"]
assert all(e.session_id == "s1" for e in engine.events)
assert all(isinstance(e, AgentPipelineStarted) for e in engine.events)

View File

@ -0,0 +1,123 @@
from __future__ import annotations
import datetime as _dt
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from everalgo.types import ChatMessage, MemCell
from everalgo.types import Episode as AlgoEpisode
from everos.core.persistence import EntryId
from everos.memory import IngestResult
from everos.memory.events import EpisodeExtracted, UserPipelineStarted
from everos.memory.extract.pipeline.user_memory import UserMemoryPipeline
from everos.memory.models import CanonicalMessage
def _sample_memcell() -> MemCell:
return MemCell(
items=[
ChatMessage(
id="m1",
role="user",
content="hello",
timestamp=1_700_000_000_000,
sender_id="u1",
),
],
timestamp=1_700_000_000_000,
)
class _CapturingEngine:
def __init__(self) -> None:
self.emitted: list[object] = []
async def emit(self, event: object) -> None:
self.emitted.append(event)
async def test_emit_pipeline_started_routes_through_engine() -> None:
engine = _CapturingEngine()
pipeline = UserMemoryPipeline(
episode_writer=MagicMock(),
prompt_loader=MagicMock(),
llm_client=MagicMock(),
engine=engine,
)
cell = _sample_memcell()
await pipeline._emit_pipeline_started( # noqa: SLF001 — test introspection
memcell_id="mc_a",
session_id="s1",
app_id="claude_code",
project_id="oss",
cell=cell,
)
started = [e for e in engine.emitted if isinstance(e, UserPipelineStarted)]
assert len(started) == 1
assert started[0].memcell_id == "mc_a"
assert started[0].session_id == "s1"
assert started[0].app_id == "claude_code"
assert started[0].project_id == "oss"
assert started[0].memcell is cell
@pytest.mark.asyncio
async def test_emit_episode_extracted_after_md_write() -> None:
"""Each per-sender Episode write emits EpisodeExtracted with the md entry id."""
engine = _CapturingEngine()
episode_writer = MagicMock()
episode_writer.append_entry = AsyncMock(
return_value=EntryId(prefix="ep", date=_dt.date(2026, 5, 17), seq=1)
)
episode_writer.path_for = MagicMock(
return_value="users/u1/episodes/episode-2026-05-17.md"
)
prompt_loader = MagicMock()
prompt_loader.load = MagicMock(return_value="<prompt>")
llm_client = MagicMock()
pipeline = UserMemoryPipeline(
episode_writer=episode_writer,
prompt_loader=prompt_loader,
llm_client=llm_client,
engine=engine,
)
cell = _sample_memcell()
ingested = IngestResult(
session_id="s1",
messages=[
CanonicalMessage(
message_id="m1",
session_id="s1",
sender_id="u1",
role="user",
timestamp=_dt.datetime.fromtimestamp(1_700_000_000, tz=_dt.UTC),
text="hello",
)
],
)
algo_ep = AlgoEpisode(
owner_id="u1", episode="they said hello", timestamp=1_700_000_000_000
)
with patch.object( # noqa: SLF001
pipeline._ep_ext, "aextract", new=AsyncMock(return_value=algo_ep)
):
outcome = await pipeline.run(
ingested=ingested,
cells=[cell],
memcell_ids=["mc_a"],
per_cell_all_senders=[["u1"]],
)
assert outcome.status == "extracted"
extracted = [e for e in engine.emitted if isinstance(e, EpisodeExtracted)]
assert len(extracted) == 1
assert extracted[0].memcell_id == "mc_a"
assert extracted[0].episode_entry_id == "ep_20260517_00000001"
assert extracted[0].episode_text == "they said hello"
assert extracted[0].episode_timestamp_ms == 1_700_000_000_000
assert extracted[0].owner_id == "u1"