Skip to content

feat: memory evolution -- GraphRAG/consistency research + SelfEditingMemoryStrategy (#1036, #208)#1129

Merged
Aureliolo merged 5 commits intomainfrom
feat/memory-evolution-1036-208
Apr 7, 2026
Merged

feat: memory evolution -- GraphRAG/consistency research + SelfEditingMemoryStrategy (#1036, #208)#1129
Aureliolo merged 5 commits intomainfrom
feat/memory-evolution-1036-208

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

Implements Strategy 3 (self-editing memory) from design spec §7.7 and lands the GraphRAG/consistency research from #1036.

#208 -- SelfEditingMemoryStrategy

Agents now maintain structured core/archival/recall memory blocks and read/write them via six dedicated tools during execution.

Three memory tiers:

  • Core (SEMANTIC + core tag): Always injected as a SYSTEM message. Agents read/write via core_memory_read / core_memory_write.
  • Archival (any non-WORKING category): Never auto-injected; agents search on demand via archival_memory_search / archival_memory_write.
  • Recall (EPISODIC): Point-in-time lookup by ID via recall_memory_read / recall_memory_write.

New files:

  • src/synthorg/memory/self_editing.py -- SelfEditingMemoryStrategy, SelfEditingMemoryConfig, six tool name constants, _extract_str / _format_entries / _format_error_oversized helpers
  • src/synthorg/memory/tools.py -- six BaseTool wrappers, create_self_editing_tools(), registry_with_memory_tools() updated to handle both ToolBased and SelfEditing strategies
  • src/synthorg/observability/events/memory.py -- nine new MEMORY_SELF_EDIT_* event constants
  • tests/unit/memory/test_self_editing.py -- 75 unit tests covering config validation, all six tools, dispatch error handling, registry fallback, _extract_str type safety, content/ID length limits

Security hardening:

  • handle_tool_call catches generic Exception and returns a generic "Error: Memory operation failed." -- raw backend error details (e.g. SQLite messages) are never exposed to the LLM
  • _MAX_CONTENT_LEN = 50_000 and _MAX_MEMORY_ID_LEN = 256 guards on all write handlers and recall_memory_read prevent unbounded writes from LLM-supplied values
  • cat_raw never echoed into error messages (fixed to generic "Unknown memory category.")

Config guardrails:

  • archival_categories validator rejects WORKING (session-scoped, must not be persisted)
  • archival_categories must be non-empty (empty set would silently block all archival writes)
  • allow_core_writes=False locks core memory to read-only for that agent
  • core_max_entries cap prevents unbounded core memory growth

#1036 -- GraphRAG / Consistency Research

  • docs/design/memory-consistency.md -- new design page: append-only writes, MVCC snapshot reads, conflict handling, deployment rollout
  • docs/design/memory.md -- SharedKnowledgeStore cross-reference to memory-consistency.md

Documentation updates

  • docs/DESIGN_SPEC.md -- indexed memory-consistency.md in the design pages table
  • CLAUDE.md -- added all nine MEMORY_SELF_EDIT_* constants to the logging events list

Closes #208
Closes #1036

…MemoryStrategy (#1036, #208)

## #1036 -- Memory Evolution Research

Add three ADR entries (D25-D27) and supporting design docs.

**D25 -- GraphRAG Evaluation**: Defer GraphRAG, stay on Mem0 + Qdrant.
Benchmarks show +15-25% multi-hop reasoning at 2-3x infra cost and 200-400ms
vs 50-150ms query latency. Current episodic/semantic use cases do not require
entity traversal. Incremental upgrade path documented.

**D26 -- Multi-Agent Memory Consistency**: Adopt append-only writes +
MVCC-style snapshot reads for SharedKnowledgeStore. CRDT rejected (space
overhead, tombstone resurrection). Event sourcing rejected (compaction
complexity). Append-only + MVCC provides audit trail and rollback.

**D27 -- RL Consolidation Feasibility**: RL not recommended for MVP.
Reward function is unsolved, ground truth requires ~1000 labeled sessions, and
training infra cost exceeds token savings by ~12 months at current scale.

New docs: docs/design/memory-consistency.md, docs/reference/rl-consolidation-feasibility.md
Updated: docs/design/memory.md (Strategy 3 status, GraphRAG migration path)

## #208 -- SelfEditingMemoryStrategy (Strategy 3)

Implement the self-editing memory injection strategy. Agents maintain
structured core/archival/recall memory tiers and read/write them via tools
during execution.

**Three tiers:**
- Core: SEMANTIC + core tag, injected as SYSTEM message on every turn
- Archival: non-WORKING categories, tool-searched via archival_memory_search
- Recall: EPISODIC, ID-based lookup via recall_memory_read

**New classes:**
- SelfEditingMemoryConfig: frozen Pydantic config (token budgets, tag names,
  safety flags including allow_core_writes)
- SelfEditingMemoryStrategy: implements MemoryInjectionStrategy protocol;
  prepare_messages injects core block; 6 handle_tool_call handlers

**6 new tool wrappers** in tools.py: CoreMemoryReadTool, CoreMemoryWriteTool,
ArchivalMemorySearchTool, ArchivalMemoryWriteTool, RecallMemoryReadTool,
RecallMemoryWriteTool + create_self_editing_tools factory.

**Event constants** (9): MEMORY_SELF_EDIT_TOOL_EXECUTE, CORE_READ/WRITE,
CORE_WRITE_REJECTED, ARCHIVAL_SEARCH/WRITE, RECALL_READ/WRITE, WRITE_FAILED.

**Validator updates** in retrieval_config.py: SELF_EDITING added to supported
strategies; diversity_penalty and query_reformulation validators already reject
SELF_EDITING via existing conditions.

**53 new tests** across 14 test classes covering config validation, strategy
init, prepare_messages, tool definitions, all 6 tool handlers, and
registry_with_memory_tools augmentation. Full suite: 1551 passed.

Closes #1036
Closes #208
The test_client fixture in tests/unit/api/conftest.py creates a full
Litestar application (create_app) for every test. Under the full test
suite (15k+ tests, 8 xdist workers), these heavyweight app objects
accumulate faster than Python's cyclic GC can collect them.

At ~98% of the full suite run, combined memory pressure causes
worker crashes (process crash, not Python exception) when six specific
api/controllers tests trigger Litestar's Pydantic v1 compat layer:
  - test_update_department_matching_etag
  - test_get_after_activate
  - test_create_team_blank_name_rejected
  - test_trends_success_rate
  - test_list_projects_after_create
  - test_returns_blueprint_info_fields

All six pass when run in isolation or as the api/controllers batch
(824 tests), confirming the crash is OOM-driven, not a logic bug.

Fix: add gc.collect() after the with TestClient(app) as client: block
exits. This forces immediate collection of the app, its services, and
any asyncio tasks retained by reference cycles, preventing the
accumulation that triggers the crash.

Also fix mypy error in test_self_editing.py: ChatMessage.content is
str | None so the 'in' operator requires a non-None guard first.
- security: sanitize handle_tool_call error to avoid leaking backend details
- security: add _MAX_CONTENT_LEN (50k) and _MAX_MEMORY_ID_LEN (256) guards
  to all write handlers and recall_memory_read
- types: change handler agent_id params from str to NotBlankStr (CLAUDE.md
  convention for identifier fields)
- config: add _archival_categories_not_empty validator to SelfEditingMemoryConfig
- refactor: extract _core_query() helper shared by prepare_messages, core read,
  and core write handlers (also reduces _handle_core_memory_write below 50 lines)
- refactor: introduce _format_error_oversized() to DRY oversized-content errors
- refactor: simplify handle_tool_call() -- return directly in try block
- fix: change cat_raw error message to generic "Unknown memory category."
- docs: add Me3 advisory race-window note to _handle_core_memory_write docstring
- docs: index memory-consistency.md in DESIGN_SPEC.md
- docs: add SharedKnowledgeStore cross-reference in memory.md
- docs: add MEMORY_SELF_EDIT_* event constants to CLAUDE.md logging section
- tests: add TestHandleToolCallDispatch -- dispatch, MemoryError/RecursionError
  re-raise, generic exception wrapping
- tests: add registry exception fallback tests (SelfEditing + ToolBased paths)
- tests: add TestExtractStr -- parametrized non-string type coverage
- tests: add content-length and memory_id-length limit tests to write/read tools
- tests: add test_empty_archival_categories_rejected
Copilot AI review requested due to automatic review settings April 7, 2026 20:02
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 7, 2026 20:03 — with GitHub Actions Inactive
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 7, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5a86b941-0274-4971-922b-6b23274b597e

📥 Commits

Reviewing files that changed from the base of the PR and between b6cd845 and f29cca1.

📒 Files selected for processing (1)
  • tests/unit/memory/test_self_editing_tools.py
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build Web
  • GitHub Check: Test (Python 3.14)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Python version requirement: 3.14+ (PEP 649 native lazy annotations)

No from __future__ import annotations -- Python 3.14 has PEP 649

PEP 758 except syntax: use except A, B: (no parentheses) -- ruff enforces this on Python 3.14

Type hints: all public functions, mypy strict mode

Docstrings: Google style, required on public classes/functions (enforced by ruff D rules)

Immutability: create new objects, never mutate existing ones. For non-Pydantic internal collections (registries, BaseTool), use copy.deepcopy() at construction + MappingProxyType wrapping for read-only enforcement.

Config vs runtime state: frozen Pydantic models for config/identity; separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.

Models: Pydantic v2 (BaseModel, model_validator, computed_field, ConfigDict). Use allow_inf_nan=False in all ConfigDict declarations to reject NaN/Inf in numeric fields at validation time.

Use @computed_field for derived values instead of storing + validating redundant fields (e.g., TokenUsage.total_tokens)

Use NotBlankStr (from core.types) for all identifier/name fields -- including optional (NotBlankStr | None) and tuple (tuple[NotBlankStr, ...]) variants -- instead of manual whitespace validators.

Async concurrency: prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g., multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare create_task.

Line length: 88 characters (ruff)

Functions: < 50 lines, files < 800 lines

Errors: handle explicitly, never silently swallow

Validate: at system boundaries (user input, external APIs, config files)

Variable name: always logger (not _logger, not log)

All error paths must log at WARNING or ERROR with context before raising

All state transitions must log at INFO

DEBUG for object creation, internal flow, entry/exit of key functions

Vendor-...

Files:

  • tests/unit/memory/test_self_editing_tools.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Markers: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, @pytest.mark.slow

Coverage: 80% minimum (enforced in CI)

Async: asyncio_mode = "auto" -- no manual @pytest.mark.asyncio needed

Timeout: 30 seconds per test (global in pyproject.toml -- do not add per-file pytest.mark.timeout(30) markers; non-default overrides like timeout(60) are allowed)

Parallelism: pytest-xdist via -n 8 -- ALWAYS include -n 8 when running pytest locally, never run tests sequentially.

Parametrize: Prefer @pytest.mark.parametrize for testing similar cases

Property-based testing with Hypothesis: use @given + @settings, profiles configured in tests/conftest.py: ci (deterministic, max_examples=10 + derandomize=True), dev (1000 examples), fuzz (10,000 examples, no deadline), extreme (500,000 examples, no deadline). Controlled via HYPOTHESIS_PROFILE env var.

When Hypothesis finds a failure, it is a real bug -- the shrunk example is saved to ~/.synthorg/hypothesis-examples/ but is not replayed automatically. Fix the underlying bug and add an explicit @example(...) decorator to permanently cover the case in CI.

Flaky tests: NEVER skip, dismiss, or ignore flaky tests -- always fix them fully and fundamentally. For timing-sensitive tests, mock time.monotonic() and asyncio.sleep() to make them deterministic. For tasks that must block indefinitely, use asyncio.Event().wait() instead of asyncio.sleep(large_number).

Files:

  • tests/unit/memory/test_self_editing_tools.py

⚙️ CodeRabbit configuration file

Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare @settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which @given() honors automatically.

Files:

  • tests/unit/memory/test_self_editing_tools.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/memory/**/*.py : Memory package (memory/): pluggable MemoryBackend protocol, backends/ (Mem0 adapter), retrieval pipeline (ranking, RRF fusion, injection, formatting, non-inferable filtering), shared org memory (org/), consolidation/archival (density-aware: DensityClassifier, AbstractiveSummarizer, ExtractivePreserver, DualModeConsolidationStrategy)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to src/synthorg/memory/**/*.py : Use MemoryBackend protocol with pluggable backends (Mem0 adapter available at backends/mem0/) for persistent agent memory
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue — DESIGN_SPEC.md is a pointer file linking to 7 design pages (Agents, Organization, Communication, Engine, Memory, Operations)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue. DESIGN_SPEC.md is a pointer file linking to the 12 design pages.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: If implementation deviates from the design spec (better approach found, scope evolved, etc.), alert the user and explain why -- user decides whether to proceed or update the spec. Do NOT silently diverge.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: When approved deviations occur, update the relevant `docs/design/` page to reflect the new reality
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Every implementation plan must be presented to the user for accept/deny before coding starts
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: At every phase of planning and implementation, be critical -- actively look for ways to improve the design in the spirit of what we're building (robustness, correctness, simplicity, future-proofing where it's free)
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Surface improvements as suggestions, not silent changes -- user decides
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Prioritize issues by dependency order, not priority labels -- unblocked dependencies come first
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Commits: `<type>: <description>` -- types: feat, fix, refactor, docs, test, chore, perf, ci. Enforced by commitizen (commit-msg hook)
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Signed commits: required on `main` via branch protection -- all commits must be GPG/SSH signed
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Branches: `<type>/<slug>` from main
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Pre-commit hooks: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint (Dockerfile linting), golangci-lint + go vet (CLI), no-em-dashes, no-redundant-timeout, eslint-web (web dashboard)
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Hookify rules: block-pr-create (blocks direct gh pr create), enforce-parallel-tests (enforces -n 8 with pytest), no-cd-prefix (blocks cd prefix in Bash commands), no-local-coverage (blocks --cov flags locally)
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Pre-push hooks: mypy type-check (affected modules only) + pytest unit tests (affected modules only) + golangci-lint + go vet + go test (CLI) + eslint-web (web dashboard). Foundational module changes (core, config, observability) or conftest changes trigger full runs.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Pre-commit.ci: autoupdate disabled (autoupdate_schedule: never) -- Dependabot owns hook version bumps via pre-commit ecosystem
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: GitHub issue queries: use `gh issue list` via Bash (not MCP tools) -- MCP list_issues has unreliable field data
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Merge strategy: squash merge -- PR body becomes the squash commit message on main. Trailers (e.g., Release-As, Closes `#N`) must be in the PR body to land in the final commit.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: PR issue references: preserve existing `Closes `#NNN`` references -- never remove unless explicitly asked
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: After finishing an issue implementation: always create a feature branch (`<type>/<slug>`), commit, and push -- do NOT create a PR automatically. Do NOT leave work uncommitted on main.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: NEVER create a PR directly -- gh pr create is blocked by hookify. ALWAYS use `/pre-pr-review` to create PRs -- it runs automated checks + review agents + fixes before creating the PR.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: For trivial/docs-only changes: `/pre-pr-review quick` skips agents but still runs automated checks
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: After the PR exists, use `/aurelio-review-pr` to handle external reviewer feedback
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: Fix everything valid -- never skip: When review agents find valid issues (including pre-existing issues in surrounding code, suggestions, and findings adjacent to the PR's changes), fix them all. No deferring, no "out of scope" skipping.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: NEVER use `cd` in Bash commands -- the working directory is already set to the project root. Use absolute paths or run commands directly. Exception: `bash -c "cd <dir> && <cmd>"` is safe (runs in a child process). Use this for tools without a -C flag.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: NEVER use Bash to write or modify files -- use the Write or Edit tools. Do not use cat >, cat << EOF, echo >, echo >>, sed -i, python -c, or tee to create or modify files.
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: A PostToolUse hook (scripts/check_web_design_system.py) enforces design system rules on every Edit/Write to web/src/
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:46:23.855Z
Learning: See web/CLAUDE.md for the full component inventory, design token rules, and post-training references (TS6, Storybook 10)
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/memory/**/*.py : Memory package (memory/): pluggable MemoryBackend protocol, backends/ (Mem0 adapter), retrieval pipeline (ranking, RRF fusion, injection, formatting, non-inferable filtering), shared org memory (org/), consolidation/archival (density-aware: DensityClassifier, AbstractiveSummarizer, ExtractivePreserver, DualModeConsolidationStrategy)

Applied to files:

  • tests/unit/memory/test_self_editing_tools.py
🔇 Additional comments (8)
tests/unit/memory/test_self_editing_tools.py (8)

1-107: Well-structured test helpers and setup.

The helper functions effectively reduce boilerplate while maintaining test clarity. The _make_backend mock factory with spec=MemoryBackend ensures type safety, and the conditional default for backend.get at line 70 correctly handles both empty and populated entry tuples.


114-217: Comprehensive core memory tool tests.

Good coverage of success and error paths including:

  • Content validation (blank, oversized)
  • Configuration guards (allow_core_writes=False, core_max_entries)
  • Correct category and tag assignment

The defensive pattern of asserting both result.is_error and not backend.store.called in error cases (lines 179-180, 195-196, 215-216) ensures no side effects occur on validation failures.


224-302: Good use of parametrized tests for edge cases.

The test_execute_non_integer_limit_defaults_to_config parametrized test (lines 281-301) effectively covers various invalid limit types, ensuring robust input handling. The assertion at line 301 (query.limit <= 7) correctly verifies the clamping behavior rather than exact equality.


309-385: Complete archival write test coverage.

Tests correctly verify both positive (auto-tag applied, memory ID returned) and negative (working category rejected, blank/oversized content rejected) scenarios. The pair of tests at lines 311-337 effectively validates the write_auto_tag configuration toggle.


392-457: Thorough recall read validation tests.

The parametrized test at lines 442-456 covers important non-string type rejections. Good boundary testing with _MAX_MEMORY_ID_LEN + 1 at line 436.


464-520: Recall write tests verify forced EPISODIC category.

Line 476 correctly asserts that RecallMemoryWriteTool forces MemoryCategory.EPISODIC regardless of caller intent, matching the design spec's recall tier definition.


527-617: Registry integration tests cover all strategy paths.

The identity check at line 562 (assert result is base_registry) correctly verifies that None strategy returns the original registry unchanged. The regression test at lines 564-581 ensures backward compatibility with ToolBasedInjectionStrategy.

The fallback tests (lines 583-617) appropriately use patches to simulate internal failures, verifying graceful degradation to the original registry.


625-668: Factory function tests verify complete tool creation.

The test_agent_id_bound_to_tools test (lines 659-668) provides valuable integration verification by executing a tool and checking that the bound agent_id propagates correctly to the backend call.


Walkthrough

This pull request implements self-editing memory injection strategy for agents, adds comprehensive architectural research documentation, and extends the memory system with multi-agent consistency support. The implementation includes a new SelfEditingMemoryStrategy with six tool wrappers for structured read/write access to core, archival, and recall memory blocks. Three architecture decision records document choices for Mem0/Qdrant retention over GraphRAG, MVCC-style consistency with append-only writes for shared knowledge, and deferral of RL-based consolidation to future scaling phases. A new design document specifies the consistency model with conflict handling, time-travel query extensions, and staged rollout plan. Supporting changes include observability events, configuration validation, registry integration, and extensive test coverage.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.32% which is insufficient. The required threshold is 40.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly references the main PR objectives: SelfEditingMemoryStrategy implementation (#208) and GraphRAG/consistency research (#1036).
Description check ✅ Passed The description clearly explains the implementation of Strategy 3 (self-editing memory) with three memory tiers, new files, security hardening, and config guardrails, plus GraphRAG/consistency research deliverables.
Linked Issues check ✅ Passed All objectives from #208 and #1036 are met: SelfEditingMemoryStrategy with three memory tiers, six tools, MemoryInjectionStrategy compliance [#208]; GraphRAG ADR, consistency model design, RL feasibility analysis [#1036].
Out of Scope Changes check ✅ Passed All changes are directly aligned with PR objectives: self-editing memory implementation, tool integration, observability events, design documentation, and comprehensive test coverage. No unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

Tools execution failed with the following error:

Failed to run tools: Stream setup permanently failed: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA f29cca1.
Ensure that dependencies are being submitted on PR branches. Re-running this action after a short time may resolve the issue. See the documentation for more information and troubleshooting advice.

Scanned Files

None

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the SelfEditingMemoryStrategy, which enables agents to manage core, archival, and recall memory tiers through a set of six dedicated tools. It also establishes a multi-agent memory consistency model for shared knowledge based on append-only writes and MVCC snapshot reads, accompanied by comprehensive architectural documentation and feasibility analyses for future memory evolutions. The review feedback identifies critical Python 3 syntax errors in exception handling across several files and suggests improving the maintainability of error messages by dynamically generating valid category lists from enums and configurations.

estimator=self._token_estimator,
token_budget=token_budget,
)
except builtins.MemoryError, RecursionError:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This except syntax is for Python 2. In Python 3, multiple exceptions must be grouped in a tuple. This will cause a SyntaxError at runtime.

        except (builtins.MemoryError, RecursionError):

)
try:
return await self._dispatch_tool_call(tool_name, arguments, agent_id)
except builtins.MemoryError, RecursionError:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This except syntax is for Python 2. In Python 3, multiple exceptions must be grouped in a tuple. This will cause a SyntaxError at runtime.

        except (builtins.MemoryError, RecursionError):

limit_raw = arguments.get("limit", self._config.archival_search_limit)
try:
limit = int(limit_raw)
except TypeError, ValueError:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This except syntax is for Python 2. In Python 3, multiple exceptions must be grouped in a tuple. This will cause a SyntaxError at runtime.

        except (TypeError, ValueError):

if isinstance(strategy, SelfEditingMemoryStrategy):
try:
augmented = _build_self_editing_registry(tool_registry, strategy, agent_id)
except MemoryError, RecursionError:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This except syntax is for Python 2. In Python 3, multiple exceptions must be grouped in a tuple. This will cause a SyntaxError at runtime.

        except (MemoryError, RecursionError):

Comment on lines +656 to +659
return (
f"{ERROR_PREFIX} Unknown memory category. "
"Valid values: episodic, semantic, procedural, social."
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message for an unknown category hardcodes the list of valid values. This could become out of sync if the MemoryCategory enum changes. It would be more maintainable to generate this list dynamically.

                valid_values = ", ".join(sorted(c.value for c in MemoryCategory if c != MemoryCategory.WORKING))
                return (
                    f"{ERROR_PREFIX} Unknown memory category. "
                    f"Valid values: {valid_values}."
                )

Comment on lines +708 to +713
if category not in self._config.archival_categories:
return (
f"{ERROR_PREFIX} Category {category.value!r} cannot be "
"written to archival memory. "
"Valid values: episodic, semantic, procedural, social."
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message for an invalid category hardcodes the list of valid values. This could become out of sync with the archival_categories configuration. It would be more maintainable to generate this list dynamically from the configuration.

        if category not in self._config.archival_categories:
            valid_values = ", ".join(sorted(c.value for c in self._config.archival_categories))
            return (
                f"{ERROR_PREFIX} Category {category.value!r} cannot be "
                "written to archival memory. "
                f"Valid values: {valid_values}."
            )

coderabbitai[bot]
coderabbitai bot previously approved these changes Apr 7, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements the self-editing memory injection strategy (Strategy 3) with dedicated core/archival/recall read/write tools, and adds documentation for GraphRAG/consistency research and rollout decisions.

Changes:

  • Added SelfEditingMemoryStrategy + SelfEditingMemoryConfig with six self-editing tools and size/exception guardrails.
  • Integrated self-editing tools into ToolRegistry augmentation alongside existing tool-based memory strategy.
  • Added observability event constants, extensive unit tests, and new/updated design & decision documentation (memory consistency, GraphRAG migration path, RL feasibility).

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/synthorg/memory/self_editing.py New self-editing memory strategy, tool schemas, handlers, limits, logging.
src/synthorg/memory/tools.py Adds six BaseTool wrappers + registry augmentation for self-editing strategy.
src/synthorg/observability/events/memory.py Adds self-editing memory event constants.
src/synthorg/memory/retrieval_config.py Allows SELF_EDITING as a supported injection strategy.
src/synthorg/memory/__init__.py Exposes self-editing config/strategy in package exports.
tests/unit/memory/test_self_editing.py New unit test suite covering config, tools, dispatch, limits, and registry behavior.
tests/unit/memory/test_retrieval_config.py Updates strategy validation test to accept SELF_EDITING.
tests/unit/memory/test_init.py Updates __all__ expectations to include self-editing exports.
tests/unit/api/conftest.py Adds post-fixture gc.collect() to reduce OOM risk in large test runs.
docs/design/memory.md Updates self-editing strategy section and links to consistency doc + GraphRAG migration tip.
docs/design/memory-consistency.md New consistency model doc (append-only + MVCC snapshot reads).
docs/DESIGN_SPEC.md Indexes the new memory consistency design page.
docs/architecture/decisions.md Adds decisions D25–D27 on memory evolution/consistency/RL consolidation.
docs/reference/rl-consolidation-feasibility.md New feasibility analysis reference page.
CLAUDE.md Adds self-editing memory event constants to the logging events list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +650 to +666
categories: frozenset[MemoryCategory] | None = None
cat_raw = arguments.get("category")
if cat_raw is not None:
try:
categories = frozenset({MemoryCategory(str(cat_raw))})
except ValueError:
return (
f"{ERROR_PREFIX} Unknown memory category. "
"Valid values: episodic, semantic, procedural, social."
)

limit_raw = arguments.get("limit", self._config.archival_search_limit)
try:
limit = int(limit_raw)
except TypeError, ValueError:
limit = self._config.archival_search_limit
limit = max(1, min(limit, self._config.archival_search_limit))
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

archival_memory_search currently allows querying any MemoryCategory (including WORKING) and, when no category is provided, it passes categories=None which typically searches across all categories. That breaks the tier contract (“archival = non-WORKING only”) and can leak WORKING/session-scoped memories through the archival tool. Consider defaulting categories to self._config.archival_categories when omitted, and rejecting/ignoring category filters not in self._config.archival_categories (especially WORKING).

Copilot uses AI. Check for mistakes.
found=entry is not None,
)
if entry is None:
return f"{ERROR_PREFIX} Memory not found: {memory_id!r}"
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recall_memory_read retrieves an entry by ID but does not enforce that the fetched entry is EPISODIC. As written, an agent can use IDs surfaced by other tools (e.g., core_memory_read outputs id=...) to fetch non-episodic entries via recall_memory_read, undermining the intended tier separation. Consider validating entry.category == MemoryCategory.EPISODIC and returning an error otherwise.

Suggested change
return f"{ERROR_PREFIX} Memory not found: {memory_id!r}"
return f"{ERROR_PREFIX} Memory not found: {memory_id!r}"
if entry.category != MemoryCategory.EPISODIC:
return (
f"{ERROR_PREFIX} Memory {memory_id!r} is not an episodic memory "
"and cannot be read via recall_memory_read."
)

Copilot uses AI. Check for mistakes.
Comment on lines +700 to +712
try:
category = MemoryCategory(str(cat_raw))
except ValueError:
return (
f"{ERROR_PREFIX} Unknown memory category. "
"Valid values: episodic, semantic, procedural, social."
)

if category not in self._config.archival_categories:
return (
f"{ERROR_PREFIX} Category {category.value!r} cannot be "
"written to archival memory. "
"Valid values: episodic, semantic, procedural, social."
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When category is not permitted by self._config.archival_categories, the error text always lists episodic, semantic, procedural, social as “Valid values”. Since archival_categories is configurable (and may exclude some of these), this message can be inaccurate. Consider rendering the allowed set from self._config.archival_categories (and ensuring WORKING is never included).

Suggested change
try:
category = MemoryCategory(str(cat_raw))
except ValueError:
return (
f"{ERROR_PREFIX} Unknown memory category. "
"Valid values: episodic, semantic, procedural, social."
)
if category not in self._config.archival_categories:
return (
f"{ERROR_PREFIX} Category {category.value!r} cannot be "
"written to archival memory. "
"Valid values: episodic, semantic, procedural, social."
valid_archival_categories = ", ".join(
sorted(
category.value
for category in self._config.archival_categories
if category is not MemoryCategory.WORKING
)
)
try:
category = MemoryCategory(str(cat_raw))
except ValueError:
return (
f"{ERROR_PREFIX} Unknown memory category. "
f"Valid values: {valid_archival_categories}."
)
if category not in self._config.archival_categories:
return (
f"{ERROR_PREFIX} Category {category.value!r} cannot be "
"written to archival memory. "
f"Valid values: {valid_archival_categories}."

Copilot uses AI. Check for mistakes.
Comment on lines +529 to +537
except Exception as exc:
logger.warning(
MEMORY_SELF_EDIT_WRITE_FAILED,
tool_name=tool_name,
agent_id=agent_id,
error=str(exc),
exc_info=True,
)
return f"{ERROR_PREFIX} Memory operation failed."
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handle_tool_call logs MEMORY_SELF_EDIT_WRITE_FAILED for any tool exception (including core/archival/recall reads and archival search). This will misclassify failures in telemetry/dashboards. Consider using a tool-generic failure event (or introducing separate *_READ_FAILED / *_SEARCH_FAILED events) and reserving WRITE_FAILED for write operations only.

Copilot uses AI. Check for mistakes.
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 7, 2026

Codecov Report

❌ Patch coverage is 97.32824% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.07%. Comparing base (f702464) to head (f29cca1).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/synthorg/memory/self_editing.py 97.29% 4 Missing and 1 partial ⚠️
src/synthorg/memory/tools.py 96.96% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1129      +/-   ##
==========================================
+ Coverage   89.03%   89.07%   +0.03%     
==========================================
  Files         824      825       +1     
  Lines       47903    48164     +261     
  Branches     4821     4845      +24     
==========================================
+ Hits        42651    42902     +251     
- Misses       4352     4359       +7     
- Partials      900      903       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…bbit

- Dynamic valid values in archival search/write error messages (Gemini)
- Add debug logging for invalid limit input fallback (silent-failure)
- Update InjectionStrategy.SELF_EDITING docstring from "future" to "implemented"
- Update README.md memory section to mention self-editing strategy
- Split test_self_editing.py (945 lines) into two files under 800-line limit
- Add parametrized tests for non-integer limit values
- Add parametrized tests for non-string memory_id values
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/unit/memory/test_self_editing_tools.py`:
- Around line 139-145: Rename the misleading test function
test_is_not_error_on_success to a name that reflects its assertion (for example
test_category_is_memory or test_tool_uses_memory_category) so it matches the
docstring and the assertion that CoreMemoryReadTool(strategy=_make_strategy(),
agent_id="agent-1").category == ToolCategory.MEMORY; update the test function
name accordingly while leaving the body (use of _make_strategy,
CoreMemoryReadTool, and ToolCategory.MEMORY) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d692d50f-a1b6-4ee5-a9bd-d4f2930c6c89

📥 Commits

Reviewing files that changed from the base of the PR and between d2cd006 and b6cd845.

📒 Files selected for processing (5)
  • README.md
  • src/synthorg/memory/injection.py
  • src/synthorg/memory/self_editing.py
  • tests/unit/memory/test_self_editing.py
  • tests/unit/memory/test_self_editing_tools.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Test (Python 3.14)
  • GitHub Check: Build Web
  • GitHub Check: Build Backend
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Python 3.14+ with PEP 649 native lazy annotations; no from __future__ import annotations

Use PEP 758 except syntax: except A, B: (no parentheses) - ruff enforces on Python 3.14

All public functions must have type hints; mypy strict mode required

Google style docstrings required on public classes and functions, enforced by ruff D rules

Create new objects instead of mutating existing ones; use copy.deepcopy() for non-Pydantic internal collections and MappingProxyType wrapping for read-only enforcement

Use frozen Pydantic models for config/identity; separate mutable-via-copy models using model_copy(update=...) for runtime state. Never mix static config fields with mutable runtime fields

Use Pydantic v2 with BaseModel, model_validator, computed_field, ConfigDict. Always use allow_inf_nan=False in all ConfigDict declarations

Use @computed_field for derived values instead of storing redundant fields. For numeric fields, use allow_inf_nan=False to reject NaN/Inf at validation time

Use NotBlankStr from core.types for all identifier/name fields (including optional and tuple variants) instead of manual whitespace validators

Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code; prefer structured concurrency over bare create_task

Line length: 88 characters (ruff)

Functions must be < 50 lines, files < 800 lines

Handle errors explicitly, never silently swallow exceptions

Validate at system boundaries (user input, external APIs, config files)

Files:

  • src/synthorg/memory/injection.py
  • tests/unit/memory/test_self_editing.py
  • src/synthorg/memory/self_editing.py
  • tests/unit/memory/test_self_editing_tools.py
src/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Every module with business logic must import from synthorg.observability import get_logger and create logger = get_logger(__name__)

Always use logger as variable name, not _logger or log

Use event name constants from domain-specific modules under synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api). Import directly: from synthorg.observability.events.<domain> import EVENT_CONSTANT

Always use structured kwargs for logging: logger.info(EVENT, key=value) - never use logger.info('msg %s', val)

All error paths must log at WARNING or ERROR with context before raising; all state transitions must log at INFO; DEBUG for object creation and internal flow

Pure data models, enums, and re-exports do NOT need logging

All provider calls go through BaseCompletionProvider which applies retry + rate limiting automatically; never implement retry logic in driver subclasses or calling code

RetryConfig and RateLimiterConfig are set per-provider in ProviderConfig; retryable errors have is_retryable=True

Maintain 80% minimum test coverage (enforced in CI)

Use vendor-agnostic names in project-owned code: example-provider, example-large-001, example-medium-001, example-small-001, large/medium/small aliases. Never use real vendor names (Anthropic, OpenAI, Claude, GPT). Tests must use test-provider, test-small-001. Vendor names only allowed in: Design ops page, .claude/ files, third-party imports, provider presets

Files:

  • src/synthorg/memory/injection.py
  • src/synthorg/memory/self_editing.py

⚙️ CodeRabbit configuration file

This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.

Files:

  • src/synthorg/memory/injection.py
  • src/synthorg/memory/self_editing.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Never use import logging, logging.getLogger(), or print() in application code; exceptions allowed only in observability module setup files

Files:

  • src/synthorg/memory/injection.py
  • src/synthorg/memory/self_editing.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Mark tests with @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, or @pytest.mark.slow

Use asyncio_mode = 'auto' for pytest - no manual @pytest.mark.asyncio needed

Global test timeout: 30 seconds per test (in pyproject.toml); non-default overrides like timeout(60) are allowed but do not add global pytest.mark.timeout(30) markers

Prefer @pytest.mark.parametrize for testing similar cases

Use Hypothesis for property-based testing with @given + @settings. Configure profiles in tests/conftest.py: ci (10 examples, deterministic), dev (1000 examples), fuzz (10,000 examples, no deadline)

Never skip, dismiss, or ignore flaky tests - fix them fully and fundamentally. Mock time.monotonic() and asyncio.sleep() for timing-sensitive tests; use asyncio.Event().wait() for indefinite blocking

Files:

  • tests/unit/memory/test_self_editing.py
  • tests/unit/memory/test_self_editing_tools.py

⚙️ CodeRabbit configuration file

Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare @settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which @given() honors automatically.

Files:

  • tests/unit/memory/test_self_editing.py
  • tests/unit/memory/test_self_editing_tools.py
🧠 Learnings (24)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/memory/**/*.py : Memory package (memory/): pluggable MemoryBackend protocol, backends/ (Mem0 adapter), retrieval pipeline (ranking, RRF fusion, injection, formatting, non-inferable filtering), shared org memory (org/), consolidation/archival (density-aware: DensityClassifier, AbstractiveSummarizer, ExtractivePreserver, DualModeConsolidationStrategy)
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Read the relevant `docs/design/` page before implementing any feature or planning any issue. Design spec is the starting point for architecture, data models, and behavior
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Alert the user and explain why if implementation deviates from the spec; do NOT silently diverge - every deviation needs explicit user approval
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Update relevant `docs/design/` page to reflect the reality when approved deviations occur
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Every implementation plan must be presented to the user for accept/deny before coding starts
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Be critical at every phase of planning and implementation, actively look for ways to improve the design. Surface improvements as suggestions, not silent changes - user decides
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Prioritize issues by dependency order, not priority labels - unblocked dependencies come first
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: ALWAYS include `-n 8` when running pytest locally - never run tests sequentially. CI uses `-n auto`
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: When Hypothesis finds a failure, fix the underlying bug and add an explicit `example(...)` decorator to permanently cover the case in CI
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Git commits follow `<type>: <description>` format with types: feat, fix, refactor, docs, test, chore, perf, ci. Enforced by commitizen
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Signed commits required on `main` via branch protection - all commits must be GPG/SSH signed
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Use branch naming `<type>/<slug>` from main
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Pre-commit hooks enforce: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint, golangci-lint, go vet, no-em-dashes, no-redundant-timeout, eslint-web
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Pre-push hooks: mypy type-check (affected modules only), pytest unit tests (affected modules only), golangci-lint, go vet, go test (CLI), eslint-web. Foundational module changes or conftest changes trigger full runs
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Never use `cd` in Bash commands - use absolute paths or run commands directly. Exception: `bash -c "cd <dir> && <cmd>"` is safe for tools without a `-C` flag
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Never use Bash to write or modify files - use the Write or Edit tools. Do not use `cat >`, `cat << EOF`, `echo >`, `echo >>`, `sed -i`, or `tee` for file creation/modification
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Use `go -C cli` (never `cd cli`) for Go CLI commands
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Enforce web design system rules via PostToolUse hook (`scripts/check_web_design_system.py`) on every Edit/Write to `web/src/`
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Use Bash for `gh issue list` queries; do not use MCP `list_issues` tool due to unreliable field data
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Use squash merge strategy - PR body becomes squash commit message on main. Preserve `Closes `#NNN`` references in PR body
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: After finishing an issue implementation, create a feature branch, commit, and push immediately - do NOT create a PR automatically or leave work uncommitted on main
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: NEVER create a PR directly with `gh pr create` (blocked by hookify) - ALWAYS use `/pre-pr-review` to create PRs. For trivial changes: `/pre-pr-review quick` skips agents but runs automated checks
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: After PR exists, use `/aurelio-review-pr` to handle external reviewer feedback
Learnt from: CR
URL: 
File: CLAUDE.md:undefined-undefined
Timestamp: 2026-04-07T20:29:21.051Z
Learning: Fix everything valid found by review agents - never skip. No deferring, no 'out of scope' skipping
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/memory/**/*.py : Memory package (memory/): pluggable MemoryBackend protocol, backends/ (Mem0 adapter), retrieval pipeline (ranking, RRF fusion, injection, formatting, non-inferable filtering), shared org memory (org/), consolidation/archival (density-aware: DensityClassifier, AbstractiveSummarizer, ExtractivePreserver, DualModeConsolidationStrategy)

Applied to files:

  • README.md
  • tests/unit/memory/test_self_editing.py
  • src/synthorg/memory/self_editing.py
  • tests/unit/memory/test_self_editing_tools.py
📚 Learning: 2026-04-06T16:35:12.934Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-06T16:35:12.934Z
Learning: Applies to **/memory/MEMORY.md : The MEMORY.md index file should contain one-line pointers to other memory files

Applied to files:

  • README.md
📚 Learning: 2026-04-06T16:35:12.934Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-06T16:35:12.934Z
Learning: Applies to **/memory/**/*.md : Memory directory files use markdown with YAML frontmatter containing name, description, and type fields

Applied to files:

  • README.md
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.

Applied to files:

  • README.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Security: SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies: disabled/weighted/per-category/milestone), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume).

Applied to files:

  • README.md
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations

Applied to files:

  • README.md
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/security/**/*.py : Security package (security/): SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)

Applied to files:

  • README.md
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...

Applied to files:

  • README.md
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • README.md
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue — DESIGN_SPEC.md is a pointer file linking to 7 design pages (Agents, Organization, Communication, Engine, Memory, Operations)

Applied to files:

  • README.md
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • README.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Engine: Agent orchestration, execution loops, parallel execution, task decomposition, routing, task assignment, centralized single-writer task state engine (TaskEngine), task lifecycle, recovery, shutdown, workspace isolation, coordination (multi-agent pipeline: TopologyDispatcher protocol, 4 dispatchers — SAS/centralized/decentralized/context-dependent, wave execution, workspace lifecycle integration, CoordinationSectionConfig company config bridge, build_coordinator factory), coordination error classification, prompt policy validation, checkpoint recovery (checkpoint/, per-turn persistence, heartbeat detection, CheckpointRecoveryStrategy), approval gate (escalation detection, context parking/resume, EscalationInfo/ResumePayload models), stagnation detection (stagnation/, StagnationDetector protocol, ToolRepetitionDetector, dual-signal analysis, corrective prompt injection), agent runtime state (AgentRuntimeState, lightweight per-agent execution status for dashboard queries and recove...

Applied to files:

  • README.md
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to src/synthorg/memory/**/*.py : Use MemoryBackend protocol with pluggable backends (Mem0 adapter available at backends/mem0/) for persistent agent memory

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to **/*.py : Use `except A, B:` (no parentheses) per PEP 758 exception syntax on Python 3.14

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-04-07T16:48:04.262Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-07T16:48:04.262Z
Learning: Applies to **/*.py : Use `except A, B:` (no parentheses) instead of `except (A, B):` for multiple exceptions—PEP 758 except syntax enforced by ruff on Python 3.14.

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (without parentheses) per PEP 758 for exception handling in Python 3.14

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (no parentheses) for exception handling — PEP 758 exception syntax enforced by ruff on Python 3.14

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Handle errors explicitly; never silently swallow exceptions

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to **/*.py : Handle errors explicitly, never silently swallow exceptions

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Use PEP 758 except syntax with `except A, B:` (no parentheses) for multiple exceptions—ruff enforces this on Python 3.14.

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Handle errors explicitly—never silently swallow exceptions.

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) — enforced by ruff on Python 3.14

Applied to files:

  • src/synthorg/memory/self_editing.py
📚 Learning: 2026-03-15T16:55:07.730Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:55:07.730Z
Learning: Applies to **/*.py : Use PEP 758 except syntax: use `except A, B:` (no parentheses) — ruff enforces this on Python 3.14.

Applied to files:

  • src/synthorg/memory/self_editing.py
🔇 Additional comments (29)
src/synthorg/memory/injection.py (1)

31-31: LGTM!

Docstring accurately updated to reflect that SELF_EDITING is now implemented, consistent with the new SelfEditingMemoryStrategy in this PR.

README.md (1)

82-82: LGTM!

README accurately updated to document all three memory injection strategies now available.

tests/unit/memory/test_self_editing.py (7)

31-76: LGTM!

Well-designed test helpers with sensible defaults. Using spec=MemoryBackend on the mock ensures type safety.


83-156: LGTM!

Comprehensive config validation tests covering defaults, bounds, WORKING rejection, immutability, and empty set rejection.


163-178: LGTM!

Constructor constraint tests properly verify backend requirement and strategy name.


185-263: LGTM!

Thorough coverage of prepare_messages behavior including core entry formatting, token budget respect, empty returns, query construction verification, and error handling.


270-296: LGTM!

Tool definition tests verify count, names, and schema presence.


303-354: LGTM!

Excellent dispatch tests covering unknown tools, system error propagation, and critically verifying that backend error details are not leaked to the LLM.


361-386: LGTM!

Comprehensive _extract_str tests covering all edge cases including non-string types, blanks, missing keys, and whitespace stripping.

tests/unit/memory/test_self_editing_tools.py (8)

45-107: LGTM!

Well-designed helpers including _DummyTool for registry augmentation testing.


152-217: LGTM!

Comprehensive CoreMemoryWriteTool tests covering successful writes, allow_core_writes guard, max entries limit, content validation, and oversized content rejection.


224-302: LGTM!

Thorough ArchivalMemorySearchTool tests covering query search, category filtering, limit clamping, validation errors, and non-integer limit fallback.


309-385: LGTM!

Comprehensive ArchivalMemoryWriteTool tests covering auto-tagging, WORKING rejection, content validation, and memory ID return.


392-457: LGTM!

Thorough RecallMemoryReadTool tests covering successful retrieval, not-found handling, blank/oversized/non-string memory_id validation.


464-520: LGTM!

Comprehensive RecallMemoryWriteTool tests verifying EPISODIC category enforcement, ID return, auto-tagging, and content validation.


527-618: LGTM!

Excellent registry integration tests covering six-tool augmentation, existing tool preservation, None handling, ToolBasedInjectionStrategy regression, and exception fallback behavior.


625-668: LGTM!

Thorough create_self_editing_tools tests verifying tool count, types, categories, names, and critically that agent_id is properly bound and passed to backend calls.

src/synthorg/memory/self_editing.py (12)

59-76: LGTM!

Well-documented tool name constants and sensible input size limits for LLM-supplied values.


77-171: LGTM!

Well-defined JSON schemas with appropriate constraints. Using MappingProxyType ensures immutability at module level.


172-222: LGTM!

Clean helper functions with clear responsibilities.


229-325: LGTM!

Well-designed frozen config with allow_inf_nan=False, appropriate field constraints, and validators that enforce WORKING exclusion and non-empty archival categories.


332-389: LGTM!

Well-implemented strategy initialization with __slots__ for memory efficiency, proper backend validation, and correct _core_query() using text=None for metadata-only filtering.


390-443: LGTM!

Well-implemented prepare_messages with correct core memory fetching, token budget enforcement via format_memory_context, and appropriate error handling that fails open (returns ()) on backend errors while propagating system errors.


444-502: LGTM!

Well-documented tool definitions with clear descriptions. Using copy.deepcopy(dict(...)) ensures schema independence.


503-570: LGTM!

Clean dispatch implementation with proper error handling. Security-conscious: returns generic "Memory operation failed." message without exposing backend error details.


575-639: LGTM!

Well-implemented core memory handlers with proper guardrails (allow_core_writes, core_max_entries). Good documentation noting the non-atomic capacity check is advisory.


640-691: LGTM!

Well-implemented archival search with proper query validation, category parsing, and limit clamping. Good defensive logging that truncates raw limit to prevent log injection.


692-738: LGTM!

Well-implemented archival write with comprehensive validation: content size limits, category validation against configured archival_categories, and conditional auto-tagging.


739-786: LGTM!

Well-implemented recall handlers with consistent validation patterns. _handle_recall_memory_write correctly forces MemoryCategory.EPISODIC as documented.

…isleading test

- Remove gc.collect() from test_client fixture teardown in api/conftest.py
  (added ~5s to each of ~250 API tests, inflating CI from ~5min to ~15min)
- Rename test_is_not_error_on_success to test_tool_uses_memory_category
  to match the actual assertion (tool.category == ToolCategory.MEMORY)
@Aureliolo Aureliolo merged commit a9acda3 into main Apr 7, 2026
34 checks passed
@Aureliolo Aureliolo deleted the feat/memory-evolution-1036-208 branch April 7, 2026 20:52
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 7, 2026 20:52 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Apr 7, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.6.4](v0.6.3...v0.6.4)
(2026-04-07)


### Features

* analytics and metrics runtime pipeline
([#226](#226),
[#225](#225),
[#227](#227),
[#224](#224))
([#1127](#1127))
([ec57641](ec57641))
* engine intelligence -- quality signals, health monitoring, trajectory
scoring, coordination metrics
([#1099](#1099))
([aac2029](aac2029)),
closes [#697](#697)
[#707](#707)
[#705](#705)
[#703](#703)
* enterprise-grade auth -- HttpOnly cookie sessions, CSRF, lockout,
session limits
([#1102](#1102))
([d3022c7](d3022c7)),
closes [#1068](#1068)
* implement core tool categories and granular sub-constraints
([#1101](#1101))
([0611b53](0611b53)),
closes [#1034](#1034)
[#220](#220)
* memory evolution -- GraphRAG/consistency research +
SelfEditingMemoryStrategy
([#1036](#1036),
[#208](#208))
([#1129](#1129))
([a9acda3](a9acda3))
* security hardening -- sandbox, risk override, SSRF self-heal, DAST fix
([#1100](#1100))
([31e7273](31e7273)),
closes [#1098](#1098)
[#696](#696)
[#222](#222)
[#671](#671)


### Bug Fixes

* harden agent identity versioning post-review
([#1128](#1128))
([8eb2859](8eb2859)),
closes [#1076](#1076)


### Documentation

* engine architecture research
([#688](#688)
[#690](#690)
[#848](#848)
[#687](#687))
([#1114](#1114))
([59b31f9](59b31f9))


### Maintenance

* add .claudeignore and split CLAUDE.md for token optimization
([#1112](#1112))
([b0fbd18](b0fbd18))
* bump github.com/sigstore/protobuf-specs from 0.5.0 to 0.5.1 in /cli in
the all group
([#1106](#1106))
([73089c9](73089c9))
* bump jsdom from 29.0.1 to 29.0.2 in /site in the all group
([#1107](#1107))
([8e99dce](8e99dce))
* bump jsdom from 29.0.1 to 29.0.2 in /web in the all group
([#1108](#1108))
([ce8c749](ce8c749))
* bump python from `fb83750` to `6869258` in /docker/backend in the all
group ([#1104](#1104))
([4911726](4911726))
* bump python from `fb83750` to `6869258` in /docker/web in the all
group ([#1103](#1103))
([87bdf09](87bdf09))
* bump the all group across 1 directory with 4 updates
([#1111](#1111))
([f702464](f702464))
* bump the all group in /docker/sandbox with 2 updates
([#1105](#1105))
([05a91ca](05a91ca))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

research: advanced memory architecture -- GraphRAG, consistency protocols, RL consolidation feat: implement self-editing memory injection strategy

2 participants