Visitar URL original
feat(examples): escape CrewAI 1.15 unified memory to OKF (#1609) by imandx05-hub · Pull Request #1821 · moorcheh-ai/memanto · GitHub
Skip to content

feat(examples): escape CrewAI 1.15 unified memory to OKF (#1609) - #1821

Closed
imandx05-hub wants to merge 4 commits into
moorcheh-ai:mainfrom
imandx05-hub:feat/crewai-unified-memory-okf
Closed

imandx05-hub wants to merge 4 commits into
moorcheh-ai:mainfrom
imandx05-hub:feat/crewai-unified-memory-okf

Conversation

@imandx05-hub

@imandx05-hub imandx05-hub commented Aug 6, 2026 •

Copy link
Copy Markdown

Bounty #1609 — Path B (CrewAI)

Closes #1609.

This adds a complete, reproducible escape path from CrewAI 1.15.12 unified memory (LanceDB) to human-readable OKF and then through Memanto's shipped migration CLI. It deliberately targets the current Memory / LanceDBStorage schema rather than treating the older long_term_memory_storage.db SQLite layout as current unified memory.

What ships

  • a read-only LanceDB adapter with schema validation, atomic output, overwrite protection, private-record exclusion by default, and opt-in secret redaction;
  • explicit field/type mapping plus canonical SHA-256 provenance for every record;
  • a realistic 8-record Aurora dataset created through CrewAI's public Memory.remember, list_records, and recall APIs — not a hand-authored JSON fixture;
  • owned, reviewable OKF Markdown, a migration manifest, a real LanceDB source store, and a live Memanto export;
  • deterministic offline recall validation with zero external LLM calls.

One-command reproduction

cd examples/migrations/crewai_unified_memory_okf
python -m pip install -r requirements.txt
python -m pip install -e ../../..
python run_demo.py

Expected terminal result: Freedom loop complete: CrewAI -> owned OKF -> Memanto-ready.

Verification

Check Result
Real CrewAI records 8
Source / declared / reconstructed SHA-256 8/8 exact
Memanto OKF mappings 8/8, 0 skipped
Offline golden recall parity 6/6 expected in top 3
Live Moorcheh import 8/8, 0 failed
Live golden recall 6/6 expected at rank #1
Live OKF export reload + mapping 8/8
Review regression suite 32/32 passed
Full repository pytest suite passed (2 POSIX-only skips)
Example docstring coverage 100% (48/48) definitions
Ruff full-repository check + format clean

Review artifacts

Safety notes

Vectors are intentionally omitted because they are derived and model-specific; all vector-free fields are preserved. Private records require --include-private. The adapter never writes to the CrewAI source and never bypasses Memanto for destination import. No credentials or account identifiers are included in the artifacts.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added a complete CrewAI unified-memory migration showcase to OKF/Memanto.
    • Supports offline generation, configurable migration, privacy controls, secret redaction, and embedding omission.
    • Added validation for field fidelity, integrity, type mapping, and semantic recall parity.
    • Included browsable memory bundles, manifests, metrics, and verified import/export evidence.
  • Documentation

    • Added setup, mapping, privacy, validation, and customization guidance.
  • Bug Fixes

    • Improved session heading compatibility, portable paths, Markdown rendering, and active-hour wording.
  • Tests

    • Added comprehensive migration and round-trip coverage.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (7)
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_indices/5147bbbb-30b3-43d8-ba25-d12f737ad1ed/page_data.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_indices/5147bbbb-30b3-43d8-ba25-d12f737ad1ed/page_lookup.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/17-7e888113-3e73-494f-aecd-347a93dbc6e1.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/19-7ac39764-b021-4727-850d-ee8e404e31f0.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551595.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551596.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/1100101101100011101000117db9b1441cb8e20a5c1b1ae0f0.lance
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7ceb5bf3-4f4d-4687-9a5a-a11453d4accf

📥 Commits

Reviewing files that changed from the base of the PR and between 34b1910 and e57b649.

📒 Files selected for processing (7)
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_indices/5147bbbb-30b3-43d8-ba25-d12f737ad1ed/page_data.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_indices/5147bbbb-30b3-43d8-ba25-d12f737ad1ed/page_lookup.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/17-7e888113-3e73-494f-aecd-347a93dbc6e1.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/19-7ac39764-b021-4727-850d-ee8e404e31f0.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551595.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551596.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/1100101101100011101000117db9b1441cb8e20a5c1b1ae0f0.lance

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a complete CrewAI/LanceDB-to-OKF-to-Memanto migration example with deterministic source generation, privacy-aware conversion, fidelity validation, recall checks, demo tooling, documentation, compatibility updates, and verified migration artifacts.

Changes

CrewAI to OKF migration

Layer / File(s) Summary
Deterministic source generation
examples/migrations/crewai_unified_memory_okf/generate_source.py, examples/migrations/crewai_unified_memory_okf/tests/test_migration.py
Generates eight CrewAI memories with deterministic embeddings, persistence checks, golden recall cases, and evidence output.
LanceDB-to-OKF adapter
examples/migrations/crewai_unified_memory_okf/migrate.py, examples/migrations/crewai_unified_memory_okf/MAPPING.md, examples/migrations/crewai_unified_memory_okf/README.md
Validates LanceDB records, maps memory types, preserves metadata and hashes, supports private-record filtering and secret redaction, omits embeddings, and writes atomic OKF bundles.
Pipeline orchestration and validation
examples/migrations/crewai_unified_memory_okf/run_demo.py, examples/migrations/crewai_unified_memory_okf/validate.py
Runs generation, migration, optional Memanto dry runs, hash checks, mapping checks, recall parity checks, and validation reports.
Demo recording and documentation
examples/migrations/crewai_unified_memory_okf/record_demo.py, examples/migrations/crewai_unified_memory_okf/README.md, examples/migrations/crewai_unified_memory_okf/requirements*.txt
Adds credential-free MP4 recording, dependency manifests, workflow instructions, privacy notes, and live verification instructions.
Verified migration artifacts
examples/migrations/crewai_unified_memory_okf/artifacts/verified/*
Adds verified OKF records, indexes, manifests, session data, metrics, validation evidence, and live import/export outputs.
Session summary portability
memanto/app/services/session_service.py, memanto/app/services/summary_visualization_service.py, memanto/cli/migrate/okf_loader.py, tests/test_okf.py, tests/test_session_summary_concurrency.py
Updates session headings, accepts current and legacy heading levels, uses typed text fences, formats source paths with POSIX separators, and adjusts singular-hour wording.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant run_demo
  participant CrewAI_Memory
  participant LanceDB
  participant migrate_py
  participant Memanto_CLI
  participant validate_py

  User->>run_demo: start migration showcase
  run_demo->>CrewAI_Memory: generate deterministic memories
  CrewAI_Memory->>LanceDB: persist eight records
  run_demo->>migrate_py: convert LanceDB records
  migrate_py->>Memanto_CLI: provide OKF bundle
  Memanto_CLI-->>run_demo: return dry-run evidence
  run_demo->>validate_py: validate source and bundle
  validate_py-->>User: report hash, mapping, and recall parity
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements the linked issue objectives with a reusable adapter, reproducible workflow, documentation, reports, sample bundle, and validation evidence.
Out of Scope Changes check ✅ Passed The Memanto and test changes directly support migration portability, heading compatibility, path normalization, and generated artifact validation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the example migration from CrewAI 1.15 unified memory to OKF, which is the primary change in the pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 14

🧹 Nitpick comments (14)
examples/migrations/crewai_unified_memory_okf/record_demo.py (3)

58-70: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use Popen as a context manager to close the stdout pipe.

The current code never closes process.stdout explicitly. The pipe file descriptor is released only when the object is garbage collected, which raises ResourceWarning under -W error and in test runs. A with block closes the pipe and calls wait() deterministically.

Note on the static analysis hints for this range: the command vector is a fixed list of sys.executable, a repository-relative script path, and a tempfile.TemporaryDirectory path, and shell=True is absent. The CWE-78 findings are false positives here.

♻️ Proposed context-manager form
-        process = subprocess.Popen(
-            command,
-            cwd=script_dir,
-            env=environment,
-            stdout=subprocess.PIPE,
-            stderr=subprocess.STDOUT,
-            text=True,
-            encoding="utf-8",
-            errors="replace",
-        )
-        assert process.stdout is not None
-        captured = [line.rstrip() for line in process.stdout]
-        return_code = process.wait()
+        with subprocess.Popen(
+            command,
+            cwd=script_dir,
+            env=environment,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.STDOUT,
+            text=True,
+            encoding="utf-8",
+            errors="replace",
+        ) as process:
+            assert process.stdout is not None
+            captured = [line.rstrip() for line in process.stdout]
+            return_code = process.wait()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/record_demo.py` around lines 58
- 70, Update the subprocess execution around Popen in the record-demo flow to
use the Popen instance as a context manager, keeping stdout capture and
return-code handling inside the with block so the pipe closes and the process is
waited deterministically.

82-86: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Most DECORATION members are unreachable.

Lines 82-84 replace every character outside the ASCII printable range with a space. The box-drawing characters in DECORATION (│─┌┐└┘├┤┬┴┼╭╮╰╯═║╔╗╚╝) are non-ASCII, so they are already spaces when line 86 runs. Only " +-" can ever match. Either drop the unreachable members, or move the decoration filter before the ASCII normalization.

♻️ Proposed reorder so the decoration filter applies
     for raw in lines:
         clean = ANSI_RE.sub("", raw)
+        if not clean.strip() or not (set(clean.strip()) - DECORATION):
+            continue
         clean = "".join(
             character if 32 <= ord(character) < 127 else " " for character in clean
         )
         clean = clean.strip()
-        if not clean or not (set(clean) - DECORATION):
+        if not clean:
             continue
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/record_demo.py` around lines 82
- 86, Update the cleaning logic around the clean normalization and DECORATION
check so box-drawing decoration characters are evaluated before non-ASCII
characters are replaced with spaces. Preserve the existing empty/decoration-only
check while ensuring every DECORATION member can be recognized, rather than
removing the defined decoration set.

26-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Font lookup is Windows-only.

_font searches only %WINDIR%\Fonts. On Linux and macOS every lookup falls through to ImageFont.load_default(). That returns a small bitmap font, so the requested sizes 18, 24, and 44 are ignored and the frame layout (fixed y-offsets, 25-line terminal window) no longer matches the rendered text. Pillow>=10,<13 in requirements-video.txt also allows versions before 10.1, where load_default does not accept a size argument at all.

Add a platform-independent candidate list, and prefer a scalable fallback.

♻️ Proposed cross-platform font lookup
-def _font(name: str, size: int) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
-    windows_fonts = Path(os.environ.get("WINDIR", r"C:\Windows")) / "Fonts"
-    for candidate in (windows_fonts / name, windows_fonts / "consola.ttf"):
-        if candidate.exists():
-            return ImageFont.truetype(str(candidate), size=size)
-    return ImageFont.load_default()
+FONT_DIRECTORIES = (
+    Path(os.environ.get("WINDIR", r"C:\Windows")) / "Fonts",
+    Path("/usr/share/fonts"),
+    Path("/usr/local/share/fonts"),
+    Path.home() / ".fonts",
+    Path("/System/Library/Fonts"),
+    Path("/Library/Fonts"),
+)
+FALLBACK_FONTS = (
+    "consola.ttf",
+    "DejaVuSansMono.ttf",
+    "DejaVuSans.ttf",
+    "Menlo.ttc",
+)
+
+
+def _font(name: str, size: int) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
+    for candidate_name in (name, *FALLBACK_FONTS):
+        for directory in FONT_DIRECTORIES:
+            if not directory.is_dir():
+                continue
+            for candidate in directory.rglob(candidate_name):
+                return ImageFont.truetype(str(candidate), size=size)
+    return ImageFont.load_default()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/record_demo.py` around lines 26
- 37, Update the _font helper to search platform-independent font candidates,
including common Linux and macOS locations, while retaining the Windows lookup.
Ensure candidates are checked in order and prefer an available scalable
TrueType/OpenType font before falling back to ImageFont.load_default(). Keep the
existing requested sizes for MONO, MONO_BOLD, TITLE, and SUBTITLE, and avoid
passing size to load_default for compatibility with older Pillow versions.
examples/migrations/crewai_unified_memory_okf/requirements.txt (1)

5-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add upper bounds to keep the example reproducible.

crewai, lancedb, PyYAML, pytest, and ruff all carry upper bounds. pytest-asyncio and pytest-timeout do not. pytest-asyncio has changed its default configuration across major versions. Cap both to match the rest of the file.

♻️ Proposed pin bounds
-pytest-asyncio>=0.21
-pytest-timeout>=2.1
+pytest-asyncio>=0.21,<1.3
+pytest-timeout>=2.1,<3
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/requirements.txt` around lines
5 - 6, Update the pytest-asyncio and pytest-timeout dependency entries in
requirements.txt to include upper-version bounds, matching the existing
reproducibility constraints and the file’s dependency pinning style.
examples/migrations/crewai_unified_memory_okf/migrate.py (3)

289-291: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Strip the trailing separator after truncation, as _slug does.

_slug calls .rstrip("-") after slicing at line 277. _tag slices without stripping. A value longer than 64 characters can therefore produce a tag that ends with -. Match the two helpers.

♻️ Proposed change
 def _tag(value: str) -> str:
     normalized = re.sub(r"[^a-z0-9._-]+", "-", value.lower()).strip("-")
-    return normalized[:64]
+    return normalized[:64].rstrip("-")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/migrate.py` around lines 289 -
291, Update the `_tag` helper to strip trailing hyphens after truncating the
normalized value to 64 characters, matching `_slug`’s post-slice behavior while
preserving the existing normalization and length limit.

577-577: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add help text to --max-records.

Every other argument in build_parser carries a help string. --max-records does not, so --help shows the flag without a description. The README documents the 50,000 cap on lines 76-78. State the valid range, because read_lancedb_records rejects a value outside 1 to 50,000.

♻️ Proposed change
-    parser.add_argument("--max-records", type=int, default=50_000)
+    parser.add_argument(
+        "--max-records",
+        type=int,
+        default=50_000,
+        help="Maximum records to read, between 1 and 50,000",
+    )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/migrate.py` at line 577, Update
the --max-records argument in build_parser to include help text describing its
purpose and valid range of 1 to 50,000, while preserving the existing default of
50,000 and type=int.

390-399: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated safe-target guard in two modules. _safe_output_target and _safe_generated_target apply the same rule: resolve the path, reject the filesystem anchor, the home directory, the current directory, and any path with fewer than three parts. The two copies differ only in the error message. Both guard a shutil.rmtree call, so the copies must not drift.

  • examples/migrations/crewai_unified_memory_okf/migrate.py#L390-L399: rename _safe_output_target to a shared safe_destructive_target(path, *, purpose: str) helper that takes the noun for the error message, and keep it in this module.
  • examples/migrations/crewai_unified_memory_okf/generate_source.py#L227-L236: delete _safe_generated_target and import the shared helper from migrate. generate_source.py and migrate.py already sit in the same directory and are already imported together by run_demo.py lines 12-13.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/migrate.py` around lines 390 -
399, The duplicated destructive-target validation must be centralized. In
examples/migrations/crewai_unified_memory_okf/migrate.py:390-399, rename
_safe_output_target to safe_destructive_target(path, *, purpose: str), preserve
the existing safety checks, and use purpose in the error message. In
examples/migrations/crewai_unified_memory_okf/generate_source.py:227-236, remove
_safe_generated_target and import and call migrate.safe_destructive_target with
the appropriate purpose.
examples/migrations/crewai_unified_memory_okf/README.md (1)

153-156: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Clarify the redaction sentence.

On line 155 the adverb placement in "A redacted record correctly will not pass an exact-content hash check" makes "correctly" attach to the redaction rather than to the outcome. State the expected behavior directly. Line 153 also reads more simply with "for" in place of "with respect to".

✏️ Proposed wording
-- Migration is local and read-only with respect to the CrewAI database.
+- Migration is local and read-only for the CrewAI database.
 - Secret redaction is opt-in because silent mutation would violate fidelity.
-- A redacted record correctly will not pass an exact-content hash check; the
-  manifest reports its redaction count.
+- A redacted record does not pass the exact-content hash check. This is the
+  expected result, and the manifest reports its redaction count.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/README.md` around lines 153 -
156, Update the migration guarantees in the README: replace “with respect to”
with “for” in the CrewAI database sentence, and rewrite the redaction sentence
so it directly states that a redacted record will not pass an exact-content hash
check, while preserving the manifest redaction-count detail.

Source: Linters/SAST tools

examples/migrations/crewai_unified_memory_okf/validate.py (1)

139-141: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Compare confidence with a tolerance.

Line 140 tests two floats for exact equality. The value travels from the source record through a YAML dump, a YAML load, and map_okf before it reaches this comparison. The round trip is exact today, so the check passes. It becomes brittle if the mapper ever rounds or re-derives the value, and the failure would appear as an unexplained mapping error. math is already imported on line 8.

♻️ Proposed change
                 "confidence_preserved": bool(
-                    row and float(row.get("confidence", -1)) == reconstructed.importance
+                    row
+                    and math.isclose(
+                        float(row.get("confidence", -1)),
+                        reconstructed.importance,
+                        rel_tol=1e-9,
+                        abs_tol=1e-9,
+                    )
                 ),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/validate.py` around lines 139 -
141, Update the confidence comparison in the “confidence_preserved” check to use
a small floating-point tolerance via the already imported math module instead of
exact equality, while preserving the existing missing-row and default-confidence
behavior.
examples/migrations/crewai_unified_memory_okf/tests/test_migration.py (3)

73-95: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the type-precedence order and the mapping basis.

The parametrized cases each exercise one source only. infer_memanto_type returns a (type, basis) pair and applies the precedence metadata.memory_type > categories > scope components, which MAPPING.md documents as the contract. No test proves that order, and no test asserts the returned basis. Add a case where metadata.memory_type conflicts with a category.

💚 Proposed additional test
+def test_metadata_type_wins_over_category_and_scope():
+    record = CrewAIRecord(
+        id="one",
+        content="Content",
+        scope="/goal",
+        categories=("incident",),
+        metadata={"memory_type": "decision"},
+        importance=0.5,
+        created_at="2026-08-05T00:00:00Z",
+        last_accessed="2026-08-05T00:00:00Z",
+        source="agent",
+        private=False,
+    )
+    assert infer_memanto_type(record) == ("decision", "metadata.memory_type")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/tests/test_migration.py` around
lines 73 - 95, Extend test_type_mapping_is_explicit_and_deterministic to cover
the documented precedence of metadata.memory_type over categories and scope
components, using a conflicting metadata/category case and asserting both the
inferred type and basis returned by infer_memanto_type. Add coverage for
category-over-scope precedence as needed to verify the full contract described
in MAPPING.md.

161-163: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the remaining fail-closed branches of row_to_record.

Only the missing-column branch is tested. row_to_record also rejects an empty id or content, an importance outside [0, 1], malformed JSON in categories_str or metadata_str, and a non-ISO created_at. Each is a separate guard in migrate.py. Add a parametrized negative case per branch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/tests/test_migration.py` around
lines 161 - 163, Add parametrized negative cases to
test_schema_validation_fails_closed covering row_to_record’s empty id/content,
out-of-range importance, malformed categories_str/metadata_str JSON, and non-ISO
created_at guards in migrate.py. Assert each case raises ValueError, while
retaining the existing missing-column case.

124-139: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Sensitive Data Exposure (CWE-359)

Reachability: Internal

Assert that the private record is absent from the written bundle.

This test only checks counters, while the privacy guarantee is no private bundle file exists. Add assertions on manifest["records"] IDs and that no public-only/memories/*.md file contains private or "Private content".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/tests/test_migration.py` around
lines 124 - 139, Extend the migration test around write_okf_bundle to verify the
public-only bundle contains only the public record ID in manifest["records"] and
excludes the private ID. Also inspect files under the public-only memories
directory and assert no markdown file contains “private” or “Private content”,
while preserving the existing counter assertions.
examples/migrations/crewai_unified_memory_okf/run_demo.py (1)

52-68: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a timeout to the Memanto dry-run subprocess.

subprocess.run has no timeout, and capture_output=True hides the child's output while it runs. If the memanto CLI hangs, run_demo.py blocks with no progress indication and never writes the transcript. The README states the complete run finishes in under two minutes. Set a bound and report the timeout.

♻️ Proposed change
-        result = subprocess.run(
-            [
-                sys.executable,
-                "-m",
-                "memanto",
-                "migrate",
-                "okf",
-                str(okf_bundle),
-                "--dry-run",
-            ],
-            check=False,
-            capture_output=True,
-            text=True,
-            encoding="utf-8",
-            errors="replace",
-            env=environment,
-        )
+        try:
+            result = subprocess.run(
+                [
+                    sys.executable,
+                    "-m",
+                    "memanto",
+                    "migrate",
+                    "okf",
+                    str(okf_bundle),
+                    "--dry-run",
+                ],
+                check=False,
+                capture_output=True,
+                text=True,
+                encoding="utf-8",
+                errors="replace",
+                env=environment,
+                timeout=300,
+            )
+        except subprocess.TimeoutExpired as exc:
+            raise RuntimeError(
+                "Memanto dry-run did not finish within 300 seconds"
+            ) from exc
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/run_demo.py` around lines 52 -
68, Update the Memanto dry-run subprocess invocation in run_demo.py to enforce a
timeout consistent with the documented under-two-minute runtime, and handle
subprocess.TimeoutExpired by reporting the timeout clearly and preserving the
demo’s expected failure/transcript behavior.
examples/migrations/crewai_unified_memory_okf/generate_source.py (1)

265-309: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Close the CrewAI memory store on error paths.

memory.close() runs only after every remember, list_records, and recall call succeeds. If any of them raises, the LanceDB handle stays open. A later --force run then calls shutil.rmtree on that directory, which fails on Windows while the handle is held. Wrap the store usage in try/finally.

♻️ Proposed refactor using try/finally
     ids_by_key: dict[str, str] = {}
-    for item in SOURCE_MEMORIES:
-        record = memory.remember(
-            item["content"],
-            scope=item["scope"],
-            categories=item["categories"],
-            metadata=item["metadata"],
-            importance=item["importance"],
-            source=item["source"],
-            agent_role=item["agent_role"],
-        )
-        if record is None:
-            raise RuntimeError(f"CrewAI did not persist {item['key']}")
-        ids_by_key[item["key"]] = record.id
-
-    records = memory.list_records(scope="/", limit=100)
-    if len(records) != len(SOURCE_MEMORIES):
-        raise RuntimeError(
-            f"CrewAI stored {len(records)} records, expected {len(SOURCE_MEMORIES)}"
-        )
-
-    recall_results: list[dict[str, Any]] = []
-    for item in GOLDEN_QUESTIONS:
-        matches = memory.recall(item["question"], depth="shallow", limit=3)
-        expected_id = ids_by_key[item["expected_key"]]
-        rank = next(
-            (
-                index
-                for index, match in enumerate(matches, start=1)
-                if match.record.id == expected_id
-            ),
-            None,
-        )
-        recall_results.append(
-            {
-                "question": item["question"],
-                "expected_key": item["expected_key"],
-                "expected_id": expected_id,
-                "expected_rank": rank,
-                "top_ids": [match.record.id for match in matches],
-                "top_contents": [match.record.content for match in matches],
-            }
-        )
-
-    memory.close()
+    recall_results: list[dict[str, Any]] = []
+    try:
+        for item in SOURCE_MEMORIES:
+            record = memory.remember(
+                item["content"],
+                scope=item["scope"],
+                categories=item["categories"],
+                metadata=item["metadata"],
+                importance=item["importance"],
+                source=item["source"],
+                agent_role=item["agent_role"],
+            )
+            if record is None:
+                raise RuntimeError(f"CrewAI did not persist {item['key']}")
+            ids_by_key[item["key"]] = record.id
+
+        records = memory.list_records(scope="/", limit=100)
+        if len(records) != len(SOURCE_MEMORIES):
+            raise RuntimeError(
+                f"CrewAI stored {len(records)} records, expected {len(SOURCE_MEMORIES)}"
+            )
+
+        for item in GOLDEN_QUESTIONS:
+            matches = memory.recall(item["question"], depth="shallow", limit=3)
+            expected_id = ids_by_key[item["expected_key"]]
+            rank = next(
+                (
+                    index
+                    for index, match in enumerate(matches, start=1)
+                    if match.record.id == expected_id
+                ),
+                None,
+            )
+            recall_results.append(
+                {
+                    "question": item["question"],
+                    "expected_key": item["expected_key"],
+                    "expected_id": expected_id,
+                    "expected_rank": rank,
+                    "top_ids": [match.record.id for match in matches],
+                    "top_contents": [match.record.content for match in matches],
+                }
+            )
+    finally:
+        memory.close()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/generate_source.py` around
lines 265 - 309, Wrap the CrewAI memory operations beginning with the
SOURCE_MEMORIES loop and ending after the GOLDEN_QUESTIONS processing in a
try/finally block, and move memory.close() into the finally clause. Preserve the
existing validation and result-building behavior while ensuring the store closes
if remember, list_records, or recall raises.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/decision/decision.md`:
- Around line 27-33: Update the renderer that generates the verified decision
artifacts to normalize stored source paths to portable forward-slash separators,
including the paths represented by the supporting-data entries and the
corresponding section around lines 62-68. Regenerate the affected verified
artifacts so references such as memories/decision/... resolve consistently on
POSIX systems.

In
`@examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/instruction/instruction.md`:
- Line 29: Normalize the OKF source paths to use forward slashes in all three
live-export records: update instruction.md:29 to reference
analytics-email-privacy-rule-85450f4d-2eb3-4f62-b.md, learning.md:29 to
reference aur-218-idempotency-remediation-b380bc30-d008-4fee-b.md, and
preference.md:29 to reference
sponsor-reporting-preference-e7017675-11b8-49a7-96ce-f570d402f979.md.

In
`@examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/metrics/overview.md`:
- Around line 12-16: Update the fenced Markdown blocks in the metrics overview,
including the timeline and distribution blocks, to specify the text language
identifier after each opening fence. Preserve all existing block content
unchanged.
- Line 18: Update the active-hours wording in the metrics overview so the value
1 uses the singular form “active hour” instead of “active hours,” while
preserving the plural form for values greater than one.

In
`@examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/sessions/crewai-okf-verified_2026-08-06_unknown_summary.md`:
- Line 6: Update all repeated memory headings in the document, including the
heading beginning “Original SQLite decision” and the corresponding headings at
the other specified locations, from H3 to H2 (`##`) so the hierarchy follows the
document’s existing H1.
- Line 20: Normalize all eight OKF source entries in
examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/sessions/crewai-okf-verified_2026-08-06_unknown_summary.md#L20-L20
to use forward-slash paths and identify the okf-bundle root; apply the same
portable path format to the relationship source reference in
examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/relationship/relationship.md#L29-L29.

In
`@examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/migration-manifest.json`:
- Line 4: Update write_okf_bundle so verified manifests do not use
datetime.now(timezone.utc) for created_at; require or derive a deterministic
timestamp from stable source data, or omit created_at from
reproducibility-sensitive output, ensuring identical inputs produce
byte-for-byte identical manifests.

In `@examples/migrations/crewai_unified_memory_okf/generate_source.py`:
- Around line 310-311: Update the assertion in the offline LLM validation block
to inspect offline_llm.mock_calls rather than only offline_llm.call.call_count,
so calls through call, chat, generate, or any dynamically created mock attribute
all trigger the RuntimeError.

In `@examples/migrations/crewai_unified_memory_okf/migrate.py`:
- Around line 561-563: Update the bundle replacement logic around output and
temp_root so it preserves atomic publication: move the existing output aside,
rename temp_root into output, then delete the old bundle only after the new
rename succeeds. Add the required os import and ensure cleanup does not remove
the previous bundle before the replacement is complete.
- Around line 181-183: Update the importance conversion in row_to_record to
coalesce a present-but-null row.get("importance") value to 0.5 before calling
float, while preserving the existing range validation and ValueError behavior
for invalid values.
- Around line 146-161: Update _iso_datetime to normalize ISO-8601 strings before
datetime.fromisoformat so Python 3.10 accepts timezone offsets such as +0000 and
fractional seconds with lengths other than 3 or 6 digits. Preserve UTC
normalization and the existing field-specific ValueError behavior for invalid
inputs; do not raise the project’s minimum Python version.

In `@examples/migrations/crewai_unified_memory_okf/record_demo.py`:
- Around line 172-177: The recorded demo hard-codes run counts instead of
deriving them from captured output. In record_demo.py lines 172-177, read
round-trip-report.json from the temporary output directory and use
exact_record_hashes, mapping_checks_passed, golden_recall_parity, and
exact_bundle_match for the result rows; remove or relabel the LIVE row because
the run is dry-run only. In lines 90-92, replace the fixed 8 denominator with
the observed save index or reported record count.
- Around line 90-92: Update the caption construction in the Memory Save
Completed branch of the record-processing flow to derive the denominator from
the configured SOURCE_MEMORIES dataset rather than hard-coding 8, keeping the
displayed progress count consistent when the dataset changes.

In `@examples/migrations/crewai_unified_memory_okf/run_demo.py`:
- Around line 69-74: Sanitize the transcript in run_demo.py before the
write_text call by replacing the OKF bundle path and user home directory,
including wrapped path lines, with stable placeholders. Update the committed
evidence file
examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/memanto-dry-run.txt
lines 4-19 so lines 5, 17, and 19 contain no C:\Users\Andx... paths.

---

Nitpick comments:
In `@examples/migrations/crewai_unified_memory_okf/generate_source.py`:
- Around line 265-309: Wrap the CrewAI memory operations beginning with the
SOURCE_MEMORIES loop and ending after the GOLDEN_QUESTIONS processing in a
try/finally block, and move memory.close() into the finally clause. Preserve the
existing validation and result-building behavior while ensuring the store closes
if remember, list_records, or recall raises.

In `@examples/migrations/crewai_unified_memory_okf/migrate.py`:
- Around line 289-291: Update the `_tag` helper to strip trailing hyphens after
truncating the normalized value to 64 characters, matching `_slug`’s post-slice
behavior while preserving the existing normalization and length limit.
- Line 577: Update the --max-records argument in build_parser to include help
text describing its purpose and valid range of 1 to 50,000, while preserving the
existing default of 50,000 and type=int.
- Around line 390-399: The duplicated destructive-target validation must be
centralized. In
examples/migrations/crewai_unified_memory_okf/migrate.py:390-399, rename
_safe_output_target to safe_destructive_target(path, *, purpose: str), preserve
the existing safety checks, and use purpose in the error message. In
examples/migrations/crewai_unified_memory_okf/generate_source.py:227-236, remove
_safe_generated_target and import and call migrate.safe_destructive_target with
the appropriate purpose.

In `@examples/migrations/crewai_unified_memory_okf/README.md`:
- Around line 153-156: Update the migration guarantees in the README: replace
“with respect to” with “for” in the CrewAI database sentence, and rewrite the
redaction sentence so it directly states that a redacted record will not pass an
exact-content hash check, while preserving the manifest redaction-count detail.

In `@examples/migrations/crewai_unified_memory_okf/record_demo.py`:
- Around line 58-70: Update the subprocess execution around Popen in the
record-demo flow to use the Popen instance as a context manager, keeping stdout
capture and return-code handling inside the with block so the pipe closes and
the process is waited deterministically.
- Around line 82-86: Update the cleaning logic around the clean normalization
and DECORATION check so box-drawing decoration characters are evaluated before
non-ASCII characters are replaced with spaces. Preserve the existing
empty/decoration-only check while ensuring every DECORATION member can be
recognized, rather than removing the defined decoration set.
- Around line 26-37: Update the _font helper to search platform-independent font
candidates, including common Linux and macOS locations, while retaining the
Windows lookup. Ensure candidates are checked in order and prefer an available
scalable TrueType/OpenType font before falling back to ImageFont.load_default().
Keep the existing requested sizes for MONO, MONO_BOLD, TITLE, and SUBTITLE, and
avoid passing size to load_default for compatibility with older Pillow versions.

In `@examples/migrations/crewai_unified_memory_okf/requirements.txt`:
- Around line 5-6: Update the pytest-asyncio and pytest-timeout dependency
entries in requirements.txt to include upper-version bounds, matching the
existing reproducibility constraints and the file’s dependency pinning style.

In `@examples/migrations/crewai_unified_memory_okf/run_demo.py`:
- Around line 52-68: Update the Memanto dry-run subprocess invocation in
run_demo.py to enforce a timeout consistent with the documented under-two-minute
runtime, and handle subprocess.TimeoutExpired by reporting the timeout clearly
and preserving the demo’s expected failure/transcript behavior.

In `@examples/migrations/crewai_unified_memory_okf/tests/test_migration.py`:
- Around line 73-95: Extend test_type_mapping_is_explicit_and_deterministic to
cover the documented precedence of metadata.memory_type over categories and
scope components, using a conflicting metadata/category case and asserting both
the inferred type and basis returned by infer_memanto_type. Add coverage for
category-over-scope precedence as needed to verify the full contract described
in MAPPING.md.
- Around line 161-163: Add parametrized negative cases to
test_schema_validation_fails_closed covering row_to_record’s empty id/content,
out-of-range importance, malformed categories_str/metadata_str JSON, and non-ISO
created_at guards in migrate.py. Assert each case raises ValueError, while
retaining the existing missing-column case.
- Around line 124-139: Extend the migration test around write_okf_bundle to
verify the public-only bundle contains only the public record ID in
manifest["records"] and excludes the private ID. Also inspect files under the
public-only memories directory and assert no markdown file contains “private” or
“Private content”, while preserving the existing counter assertions.

In `@examples/migrations/crewai_unified_memory_okf/validate.py`:
- Around line 139-141: Update the confidence comparison in the
“confidence_preserved” check to use a small floating-point tolerance via the
already imported math module instead of exact equality, while preserving the
existing missing-row and default-confidence behavior.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 750a2665-0f66-4b33-9fa6-f0b574269b24

📥 Commits

Reviewing files that changed from the base of the PR and between 7071b63 and b5a0917.

⛔ Files ignored due to path filters (1)
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/demo.mp4 is excluded by !**/*.mp4
📒 Files selected for processing (116)
  • examples/migrations/crewai_unified_memory_okf/.gitignore
  • examples/migrations/crewai_unified_memory_okf/MAPPING.md
  • examples/migrations/crewai_unified_memory_okf/README.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/LIVE_MOORCHEH_REPORT.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/ROUND_TRIP_REPORT.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/live-recall-report.json
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/memanto-dry-run.txt
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/memanto-live-export.txt
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/memanto-live-import.txt
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/round-trip-report.json
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/source-run.json
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/decision/decision.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/decision/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/error/error.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/error/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/goal/goal.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/goal/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/instruction/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/instruction/instruction.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/learning/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/learning/learning.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/preference/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/preference/preference.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/relationship/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/relationship/relationship.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/metrics/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/metrics/overview.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/sessions/crewai-okf-verified_2026-08-06_unknown_summary.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/sessions/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/MIGRATION_SUMMARY.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/decision/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/decision/original-sqlite-decision-43c69696-2be5-40f3-b.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/decision/postgresql-16-is-the-current-ledger-decision-84b237f2-3188-4230-9.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/error/aur-218-duplicate-invoice-root-cause-bc26de54-75d1-47bd-9.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/error/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/goal/aurora-eu-pilot-exit-goal-87b70ac8-30d2-41d0-8.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/goal/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/instruction/analytics-email-privacy-rule-85450f4d-2eb3-4f62-b.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/instruction/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/learning/aur-218-idempotency-remediation-b380bc30-d008-4fee-b.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/learning/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/preference/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/preference/sponsor-reporting-preference-e7017675-11b8-49a7-9.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/relationship/aurora-checkout-ownership-9f451abf-0167-42e6-9.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/memories/relationship/index.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/migration-manifest.json
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_deletions/10-14-15101330878227586131.arrow
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_deletions/10-15-4483833022584410694.arrow
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_deletions/11-14-18279901948944865952.arrow
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_deletions/12-15-4307397616561731929.arrow
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_deletions/13-16-9281085764415544448.arrow
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_deletions/9-12-10416088024614745721.arrow
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_deletions/9-13-17621926630412034886.arrow
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_indices/58b7cf5b-e806-4f04-b073-ca1c38616b89/page_data.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_indices/58b7cf5b-e806-4f04-b073-ca1c38616b89/page_lookup.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/0-470c183d-da5a-4147-8404-51ade9715eae.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/1-4140fbcc-3992-4374-97fd-894ac8277a6f.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/10-749de80f-be8e-46ff-84e1-f15bab8142c1.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/11-df5800e1-7304-4d37-a2d9-7baa7febce3a.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/12-2155b72d-a1bb-49b8-9ac2-e3e0c9ee2bc4.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/13-404e7e3b-301c-4966-bf11-b1e8e928e697.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/14-338497eb-6372-4a64-bf38-41d588734cef.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/15-079c952c-67a4-4c88-bb5e-64afed9dfac6.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/16-cc73b39a-0d49-4391-aa94-0351657963c6.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/2-25d9ca87-678c-4988-bb33-ee53722c2e62.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/3-9a4e9b25-f56d-4f37-8891-8dd02de96edb.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/4-10ad963a-17e4-4798-a4ff-65e4b12a1272.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/5-ab93a3ad-798a-45fe-9a22-61752c577531.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/6-26f6cd28-0be1-4542-a260-9682f987cbed.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/7-f3a04b69-6ccb-41f5-9a6c-76d494a588fa.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/8-41595046-659b-497b-bf06-6dc27d567fdc.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_transactions/9-39ab587e-6aef-413c-b57b-760c9a704cdc.txn
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551598.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551599.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551600.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551601.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551602.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551603.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551604.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551605.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551606.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551607.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551608.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551609.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551610.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551611.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551612.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551613.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/_versions/18446744073709551614.manifest
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/0000100101001010100010012751f44253b33f79f0365db781.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/0001011001110110100001005214b1470ebb2ee9251552a508.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/0011000100001111101110116b1c9142b6af9e423e4bbd1ff9.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/001101011101010011011101416fe14801b82481e541fbe19e.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/010011011110000101011100a2b2634b509c3c7a6fe2ca5d52.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/1001010000011111100100116416864ed4bb0aaeefa205c32b.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/10101110001111001011110184d7c149bbb0a60e54e3b11f0f.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/1011111010010011001011010aa3ad4ba79e7193156f933084.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/110011001010011011111011239a0a4475907220a1347dafa9.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/110100000101110101001001b8b73f47dc82f9139560a9c23a.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/1101011011110101100010008cdf584c6e9b37b69fe8f0045c.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/111000011111010110010101e88030448ea4e7d93a25110c3a.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/1111110010000011101101017aeac845f2b56559bac6bbe8d3.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/1111111010100011110111101f722b4cda88ad4761be56f0cb.lance
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/source/crewai-memory/memories.lance/data/111111110011010010001011193c6040c8bbd212f63bcc85b5.lance
  • examples/migrations/crewai_unified_memory_okf/generate_source.py
  • examples/migrations/crewai_unified_memory_okf/migrate.py
  • examples/migrations/crewai_unified_memory_okf/record_demo.py
  • examples/migrations/crewai_unified_memory_okf/requirements-video.txt
  • examples/migrations/crewai_unified_memory_okf/requirements.txt
  • examples/migrations/crewai_unified_memory_okf/run_demo.py
  • examples/migrations/crewai_unified_memory_okf/tests/test_migration.py
  • examples/migrations/crewai_unified_memory_okf/validate.py

Comment thread examples/migrations/crewai_unified_memory_okf/migrate.py Outdated
Comment thread examples/migrations/crewai_unified_memory_okf/migrate.py Outdated
Comment thread examples/migrations/crewai_unified_memory_okf/record_demo.py Outdated
Comment thread examples/migrations/crewai_unified_memory_okf/record_demo.py
Comment thread examples/migrations/crewai_unified_memory_okf/run_demo.py
@imandx05-hub

Copy link
Copy Markdown
Author

Review follow-up pushed in 443681f. It addresses the reported portability, determinism, rollback-safety, privacy, compatibility, and evidence-quality findings. Highlights:

  • restores the previous bundle if atomic publication fails, with an explicit regression test;
  • normalizes OKF paths across platforms and preserves both current H2 and legacy H3 session parsing;
  • hardens ISO timestamps, null importance, tag bounds, subprocess timeouts, and resource cleanup;
  • removes local user paths from committed transcripts and regenerates the demo from verified report values;
  • adds dependency upper bounds and complete example docstrings.

Validation after the changes:

  • review regression suite: 29/29 passed;
  • full repository pytest suite: passed (2 POSIX-only skips);
  • example docstring coverage: 100% (48/48) definitions;
  • full-repository Ruff check and format check: clean;
  • live bundle validation remains 8/8 exact, 8/8 mapped, and 6/6 recall.

Public demo: https://youtu.be/sV5yvIjbejk

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
examples/migrations/crewai_unified_memory_okf/record_demo.py (1)

83-104: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Bound the real-run subprocess.

_capture_real_run() reads process.stdout until EOF and then waits for the child process. Line [95] has no timeout. If source generation, migration, or validation stalls, record_demo.py never returns and cannot produce a video. Add a configured timeout and terminate the child process group on expiry.

Suggested fix
-            assert process.stdout is not None
-            captured = [line.rstrip() for line in process.stdout]
-            return_code = process.wait()
+            try:
+                stdout, _ = process.communicate(
+                    timeout=REAL_RUN_TIMEOUT_SECONDS
+                )
+            except subprocess.TimeoutExpired as exc:
+                process.kill()
+                process.communicate()
+                raise RuntimeError(
+                    f"Real demo run exceeded {REAL_RUN_TIMEOUT_SECONDS} seconds"
+                ) from exc
+            captured = stdout.splitlines()
+            return_code = process.returncode
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/migrations/crewai_unified_memory_okf/record_demo.py` around lines 83
- 104, Update _capture_real_run to enforce a configured timeout while consuming
the subprocess output and waiting for completion. On timeout, terminate the
child process group, ensure the process is reaped, and raise an appropriate
failure instead of hanging; preserve normal output capture and report loading
when the subprocess finishes within the timeout.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/migrations/crewai_unified_memory_okf/migrate.py`:
- Line 471: Update the migration path around safe_destructive_target to resolve
both source and output directories and reject equal, ancestor, or descendant
overlaps before creating the temporary bundle or publishing output. Preserve the
read-only source contract, including when --force is enabled, and add regression
coverage for equal, parent, and child output paths.

In `@tests/test_okf.py`:
- Around line 223-224: Update the markdown assertion in the test to require the
singular-hour text through its line terminator, preventing a substring match
against “active hours”; keep the existing memory and hour values unchanged.

---

Outside diff comments:
In `@examples/migrations/crewai_unified_memory_okf/record_demo.py`:
- Around line 83-104: Update _capture_real_run to enforce a configured timeout
while consuming the subprocess output and waiting for completion. On timeout,
terminate the child process group, ensure the process is reaped, and raise an
appropriate failure instead of hanging; preserve normal output capture and
report loading when the subprocess finishes within the timeout.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e4c49c07-f89e-4057-875b-328ff5c5e077

📥 Commits

Reviewing files that changed from the base of the PR and between b5a0917 and 443681f.

⛔ Files ignored due to path filters (1)
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/demo.mp4 is excluded by !**/*.mp4
📒 Files selected for processing (25)
  • examples/migrations/crewai_unified_memory_okf/README.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/LIVE_MOORCHEH_REPORT.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/memanto-dry-run.txt
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/decision/decision.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/error/error.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/goal/goal.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/instruction/instruction.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/learning/learning.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/preference/preference.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/relationship/relationship.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/metrics/overview.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/sessions/crewai-okf-verified_2026-08-06_unknown_summary.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/migration-manifest.json
  • examples/migrations/crewai_unified_memory_okf/generate_source.py
  • examples/migrations/crewai_unified_memory_okf/migrate.py
  • examples/migrations/crewai_unified_memory_okf/record_demo.py
  • examples/migrations/crewai_unified_memory_okf/requirements.txt
  • examples/migrations/crewai_unified_memory_okf/run_demo.py
  • examples/migrations/crewai_unified_memory_okf/tests/test_migration.py
  • examples/migrations/crewai_unified_memory_okf/validate.py
  • memanto/app/services/session_service.py
  • memanto/app/services/summary_visualization_service.py
  • memanto/cli/migrate/okf_loader.py
  • tests/test_okf.py
  • tests/test_session_summary_concurrency.py
🚧 Files skipped from review as they are similar to previous changes (16)
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/memanto-dry-run.txt
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/okf-bundle/migration-manifest.json
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/metrics/overview.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/error/error.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/instruction/instruction.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/relationship/relationship.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/evidence/LIVE_MOORCHEH_REPORT.md
  • examples/migrations/crewai_unified_memory_okf/requirements.txt
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/learning/learning.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/decision/decision.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/goal/goal.md
  • examples/migrations/crewai_unified_memory_okf/README.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/memories/preference/preference.md
  • examples/migrations/crewai_unified_memory_okf/artifacts/verified/live-export/sessions/crewai-okf-verified_2026-08-06_unknown_summary.md
  • examples/migrations/crewai_unified_memory_okf/generate_source.py
  • examples/migrations/crewai_unified_memory_okf/validate.py

Comment thread examples/migrations/crewai_unified_memory_okf/migrate.py
Comment thread tests/test_okf.py Outdated
@imandx05-hub

Copy link
Copy Markdown
Author

@mjfekri Path B bounty submission is ready for human review: all CodeRabbit threads are resolved, the focused regression suite is 32/32, the full repository test suite and Ruff checks are clean, and the public demo is linked in the PR. When convenient, could you please review it and approve the fork workflows? Thank you.

@Xenogents

Copy link
Copy Markdown
Collaborator

Thank you for submitting this PR and for participating in our bounty! We really appreciate the time and effort you put into this, it's a very solid migration.

We received a large number of submissions for this bounty. After careful review, we ultimately decided to move forward and merge only a select few high quality submissions to be used as examples on the repo. While we won't be merging this specific PR, we were pleased by the quality of your work.

Thanks again for your contributions to Memanto!

@Xenogents Xenogents closed this Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bounty#6 Migration, OKF

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BOUNTY $200] 🐜 The Great Memory Migration: Own Your Agentic Memory with Memanto + OKF

2 participants