MCPcopy Create free account
hub / github.com/Claw-AI-Lab/Claw-AI-Lab / EvolutionStore

Class EvolutionStore

backend/agent/researchclaw/evolution.py:350–478  ·  view source on GitHub ↗

JSONL-backed store for pipeline lessons.

Source from the content-addressed store, hash-verified

348
349
350class EvolutionStore:
351 """JSONL-backed store for pipeline lessons."""
352
353 def __init__(self, store_dir: Path) -> None:
354 self._dir = store_dir
355 self._dir.mkdir(parents=True, exist_ok=True)
356 self._lessons_path = self._dir / "lessons.jsonl"
357
358 @property
359 def lessons_path(self) -> Path:
360 return self._lessons_path
361
362 def append(self, lesson: LessonEntry) -> None:
363 """Append a single lesson to the store."""
364 with self._lessons_path.open("a", encoding="utf-8") as f:
365 f.write(json.dumps(lesson.to_dict(), ensure_ascii=False) + "\n")
366
367 def append_many(self, lessons: list[LessonEntry]) -> None:
368 """Append multiple lessons atomically."""
369 if not lessons:
370 return
371 with self._lessons_path.open("a", encoding="utf-8") as f:
372 for lesson in lessons:
373 f.write(json.dumps(lesson.to_dict(), ensure_ascii=False) + "\n")
374 logger.info("Appended %d lessons to evolution store", len(lessons))
375
376 def load_all(self) -> list[LessonEntry]:
377 """Load all lessons from disk."""
378 if not self._lessons_path.exists():
379 return []
380 lessons: list[LessonEntry] = []
381 for line in self._lessons_path.read_text(encoding="utf-8").splitlines():
382 line = line.strip()
383 if not line:
384 continue
385 try:
386 data = json.loads(line)
387 lessons.append(LessonEntry.from_dict(data))
388 except (json.JSONDecodeError, TypeError):
389 continue
390 return lessons
391
392 def query_for_stage(
393 self, stage_name: str, *, max_lessons: int = 5
394 ) -> list[LessonEntry]:
395 """Return the most relevant lessons for a stage, weighted by recency.
396
397 Includes lessons that directly match the stage, plus high-severity
398 lessons from related stages.
399 """
400 all_lessons = self.load_all()
401 scored: list[tuple[float, LessonEntry]] = []
402 for lesson in all_lessons:
403 weight = _time_weight(lesson.timestamp)
404 if weight <= 0.0:
405 continue
406 # Boost direct stage matches
407 if lesson.stage_name == stage_name:

Calls

no outgoing calls