mcpField
M
mem0-test-integration

mem0-test-integration

github.com/mem0aiテスト・品質68.0k328 回インストール2 日前に更新
リポジトリ

mem0-test-integration について

mem0-test-integration は、同じワークスペースとフィーチャーブランチで mem0 の統合を検証するスキルです。静的チェック、二段階テスト、API スモークテスト、任意の E2E 検証、スコアカード作成を行います。

主な機能

  1. 01統合の前提条件チェック
  2. 02インポートとバージョンの静的検査
  3. 03フラグ無効・有効の二段階テスト
  4. 04実 API のスモークテスト
  5. 05任意の E2E 検証
  6. 06Markdown と JSON のスコアカード

活用シーン

  1. 01新規 mem0 統合の検証
  2. 02フラグ無効時に既存テストが通るかの確認
  3. 03使い捨てユーザー ID による API 呼び出しの検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mem0ai/mem0 --skill mem0-test-integration

インストール後、Claude Code で/mem0-test-integrationを入力して読み込まれたか確認します。

同梱ファイルLICENSEREADME.md

詳細

mem0-test-integration

/mem0-integrate が生成した内容を検証します。同じワークスペースの同じ機能ブランチで実行します。疎結合の検証で、短時間でコンパイル時と実行時のバグを検出しますが、論理エラーは検出しません。

正式な参照元(周辺知識ではなく、これらを使用)

すべての静的チェックとスモークテストの形式は、以下の URL に照らして検証します。ステップ 3 を実行する前に、それぞれを WebFetch してください。

.mem0-integration/plan.md の Delegated skill: フィールドを確認してください。スキル URL が指定されている場合は、そのスキルを取得し、ステップ 3 の静的チェックとステップ 5 のスモークテストの両方で、その例のブロックを参照してください。

非侵襲性の契約

このスキルのすべてのチェックは、統合が追加的かつ機能フラグで制御されていることを前提とします(/mem0-integrate の「統合の原則」を参照)。具体的には次のとおりです。

  • product.json に feature_flag フィールドが含まれている必要があります。
  • ステップ 4〜6 は 2 回実行します。
    • パス A — フラグ未設定。 既存のテストはすべて合格し、スモークテスト/E2E はスキップされます。リポジトリは main と同じように動作する必要があります。この段階で失敗した場合は重大な失敗です。自己修復ループにパッチを試みさせないでください。
    • パス B — フラグ設定済み。 新しいテストが合格し、スモークテストと E2E を実行します。
  • パス A が失敗した場合、スコアカードでは non_invasive: false とし、overall: fail に、インテグレーターの修復ループが対応できない固有の理由コードを設定します。

前提条件

以下のすべてを満たしていない場合は、開始を拒否してください。

  • リポジトリのルートに .mem0-integration/ ディレクトリが存在する。
  • .mem0-integration/product.json、goal.md、plan.md を読み取ることができ、内容に矛盾がない(JSON を解析でき、ドキュメントが空でない)。
  • 現在のブランチ名が mem0-integrate/ で始まる(コンパニオンスキルによって設定されます)。無関係なブランチでの誤実行を防ぎます。
  • 作業ツリーがクリーンである。このスキルはソースファイルを変更しません。変更がある場合は、統合が編集中で、検証の準備ができていないことを意味します。
  • 統合で使用したものと同じ API キーを環境から利用できる(Platform では MEM0_API_KEY、OSS では OPENAI_API_KEY。どちらを使うかは product.json を確認してください)。対話モードではキーがない場合に確認し、CI モードでは 2 で終了します。

前提条件を満たさない場合は、理由を記述して終了してください。状態の「修正」を試みてはいけません。

パイプライン

1. 契約を確認する

以下を読み込みます。

  • product.json → 言語、製品(Platform または OSS)、mem0 のバージョン、write_site、read_site。
  • plan.md → 機械的な契約(書き込みパターン、読み取りパターン、維持する動作)。
  • goal.md → 目的(スコアカードにのみ表示し、テスト対象ではありません)。
2. 依存関係をインストールする

言語に応じて product.json から処理を分岐します。

言語コマンド
Python編集可能なインストールの場合は pip install -e .、そうでない場合は pip install -r requirements.txt。次に、固定バージョンの mem0ai がまだインストールされていなければ pip install mem0ai を実行します。
TypeScript / JavaScriptnpm install を実行します(ロックファイルから検出された場合は pnpm install または yarn install)。

インストールに失敗した場合は、stderr の末尾とともに終了コード 2 で終了します。依存関係を解決できない場合は、テストに進んではいけません。

3. 静的な健全性チェック(高速、ローカル、API 呼び出しなし)
  • インポートチェック:書き込みサイトのファイルが、想定される Mem0 のインターフェースをインポートしているかを確認します。正とするリストは、https://docs.mem0.ai/llms.txt の ## Identify the User's Setup に記載されています。

    • Platform Python → from mem0 import MemoryClient
    • Platform TS → import MemoryClient from "mem0ai"
    • OSS Python → from mem0 import Memory
    • OSS TS → import { Memory } from "mem0ai/oss"

    plan.md に委任先のスキル(例:Vercel AI)が記載されている場合は、上記のリストではなく、そのスキルのインポートシグネチャを使用します。不一致がある場合は、行番号を付けて失敗とします。

  • バージョンチェック:インストール済みの mem0ai バージョンが、このスキルの mem0_tested_versions で指定された範囲内であるかを確認します。範囲外の場合は警告しますが、続行します。

  • 型チェック(TS のみ):tsc --noEmit または tsup --dts を実行します。終了コードが 0 以外の場合は失敗とします。

  • Lint(リポジトリにリンターが設定されている場合):リポジトリ独自の lint コマンドを実行します。このスキルによる変更が原因の lint エラーは失敗とし、既存の lint エラーは警告として通知します。

  • 遅延初期化チェック:product.json のパスを使って write_site と read_site のファイルを検索し、モジュールスコープ(つまり、関数、メソッド、クラス本体の内側ではない場所)にある MemoryClient( または Memory( を確認します。MemoryClient() は __init__ で API キーを検証します(Python は API に ping を送り、TS はキーが空だと例外を発生させ、バックグラウンドで ping を送ります)。また、OSS の Memory() は埋め込み/LLM プロバイダーを先行初期化することがあります。モジュールレベルでインスタンスを作成すると、インポート時に通信が発生し、キーが未設定の場合に Pass A のテスト収集が失敗します。該当箇所がある場合は、file:line と /mem0-integrate のステップ 8、制約 #7 にある遅延初期化のガイダンスを示して失敗とします。

4. リポジトリ標準のテストスイートを実行する(二段階)
言語テストコマンド(優先順)
Pythonコンパニオンスキルのステップ 7 にあるテストファイルを使って pytest を実行します。該当しない場合は python -m unittest discover を実行します。
TypeScript / JavaScriptpackage.json で定義されていれば npm test を実行します。定義されていない場合は vitest または jest を自動検出します。

Pass A — feature_flag が未設定。 新規の test_mem0_* ファイルを除く、既存のテストスイート全体を実行します。すべてのテストが成功しなければなりません。 ここで失敗があると、スコアカードの non_invasive: false と記録され、重大な失敗となります。インテグレーターの自己修復ループは、この失敗に対処しません。

Pass B — feature_flag を設定(値は product.json から取得)。新しいテストも含めて、テストスイート全体を実行します。すべて成功しなければなりません。

インテグレーションに起因する失敗は、git diff main..HEAD --name-only を使って切り分けます。main に存在し、インテグレーションブランチでのみ(フラグの設定/未設定を問わず)失敗するテストファイルは、テストの成功/失敗にかかわらずスコアカードに反映します。main ですでに失敗しているテストファイルは pre_existing_unrelated として通知し、スコアカードには反映しません。ただし、ユーザーが修正できるよう、引き続き報告します。

出力は .mem0-integration/test-stdout-flag-off.log と .mem0-integration/test-stdout-flag-on.log に保存します。スコアカードには、各パスの成功/失敗を記録します。

5. スモークテスト(実際の API 呼び出し、最短の往復処理)

product.json に合わせた、スクリプト化されたエンドツーエンドのフローです。以下の呼び出し形式は最小限の例です。plan.md に委任するスキルが記載されている場合は、代わりにそのスキルの最小限の例をそのまま使用してください。検出されたスタックの標準的な形式です。

Platform(Python):

import os
import time
from mem0 import MemoryClient
c = MemoryClient()                               # MEM0_API_KEYを使用
uid = f"mem0-test-integration-{os.urandom(4).hex()}"
c.add([{"role": "user", "content": "I prefer aisle seats"}], user_id=uid)
for _ in range(10):
    hits = c.search("seat preference", filters={"user_id": uid})["results"]
    if hits:
        break
    time.sleep(2)
assert any("aisle" in h.get("memory", "") for h in hits), hits
c.delete_all(user_id=uid)                        # クリーンアップ

Platform では add は非同期です(event_id とともに status: "PENDING" を返します)。そのため、一定時間内で検索を再試行します。エンティティ ID は filters に指定し、結果は ["results"] の下に返されます。

Platform(TS): "mem0ai" の new MemoryClient({ apiKey: process.env.MEM0_API_KEY })(TS クライアントは環境変数自体を読み取りません)を使い、client.search("seat preference", { filters: { user_id: uid } }) で .results の下にヒットを取得し、client.deleteAll({ userId: uid }) で削除します。

OSS(Python / TS): デフォルト設定の Memory() / new Memory() を使用します(OpenAI LLM は OPENAI_API_KEY を使用します。Python はデフォルトでディスクに埋め込まれた Qdrant を、TS はメモリー内のベクトルストアを使用するため、リポジトリ独自の設定がサービスを指定している場合を除き、サービスは不要です)。リポジトリに、設定済みのベクトルストアサービスを含む docker-compose.yml がある場合、スキルは最初にサービスを起動し、テスト後に停止します。設定済みのバックエンドストアに接続できない場合は、修正方法を明記したわかりやすいメッセージとともに失敗します。

スモークテストでは常に、mem0-test-integration- をプレフィックスとする使い捨てのランダムな user_idを使用します。クリーンアップに失敗しても、ユーザーの実データが汚染されないようにするためです。バックグラウンドのクリーンアップ処理では、client.users() を使って Platform のエンティティを一覧表示し、type: "user" で name がそのプレフィックスから始まり、created_at が24時間より前のエントリを選び、次回の実行時にそれぞれに対して delete_all(user_id=...) を呼び出します(サーバー側でプレフィックスを指定して削除する機能はありません)。

出力は .mem0-integration/smoke-stdout.log に保存します。

6. E2E 統合テスト(アプリを起動し、フローを実行する)

ユニットテストとスモークテストで、SDK が単独で動作することを確認できます。このステップで実際の状態がわかります。統合をエンドツーエンドで実行したとき、アプリのユーザー向け出力にメモリが実際に現れるでしょうか?

plan.md に E2E recipe: セクションが含まれている必要があります(/mem0-integrate のステップ 6 で作成)。存在しない場合は、ステータスを skipped(fail ではありません)とし、リポジトリに実行可能なエントリーポイントがないことをスコアカードに記載します。

スキルが読み取るレシピのフィールド:

  • start — $PORT をネットワークポートとして使用し、アプリを起動するシェルコマンドです。バックグラウンドで実行し、標準出力/標準エラーを .mem0-integration/e2e-app.log に tee します。
  • ready_probe — 準備完了を検出する方法です。url=... status=... は HTTP エンドポイントをポーリングし、log="..." は e2e-app.log に部分文字列が出力されるのを待ちます。sleep=N は N 秒待機します(最終手段)。タイムアウトは最大 60 秒です。
  • compose_services — 任意です。指定されている場合は、start の前に docker compose up -d <services> で起動し、最後に docker compose down で停止します。
  • write_call — Mem0 の書き込みパスを 1 回だけ実行します。出力は取得され、失敗時に表示されます。タイムアウトは最大 60 秒です。
  • write_async_wait_ms — 非同期メモリのフラッシュが完了するよう、write_call の後に待機する時間です。デフォルトは 0 です。
  • read_call — Mem0 の読み取りパスを実行します。通常は、保存されたメモリが表示されるはずの新しいセッションまたは新しいリクエストを使用します。
  • read_assert — read_call の標準出力に含まれている必要がある部分文字列、regex=...、または jsonpath=<expr>=<value> です。これが E2E の合格条件です。

実行順序:

  1. 一時的な TCP ポートを割り当て、PORT としてエクスポートします。
  2. MEM0_USER_ID に使い捨ての mem0-test-integration-<rand> 値を設定してエクスポートします。レシピでクリーンアップが必要な場合に、アプリがスモークテストと同じスコープを使えるようにします。
  3. compose_services が指定されている場合は起動します。
  4. start をバックグラウンドで実行します。
  5. 成功するか 60 秒でタイムアウトするまで ready_probe をポーリングします。タイムアウトした場合は失敗です。
  6. write_call を実行します。終了コードが 0 以外の場合は失敗とします(ただしクリーンアップは続行します)。
  7. write_async_wait_ms の時間だけスリープします。
  8. read_call を実行します。
  9. read_assert を read_call の標準出力に対して評価します。一致しない場合は失敗です。
  10. クリーンアップします(失敗時も必ず実行):アプリに SIGTERM を送信し、5 秒後に SIGKILL を送信します。サービスを起動した場合は docker compose down を実行し、Platform シナリオでは使い捨ての MEM0_USER_ID に対して delete_all を実行します。

失敗した場合、スコアカードには以下が含まれます。

  • e2e-app.log の末尾 40 行
  • write_call の全出力
  • read_call の全出力
  • read_assert の期待値と実際の値
7. スコアカード

.mem0-integration/scorecard.md と .mem0-integration/scorecard.json を作成します。

{
  "timestamp": "2026-04-20T14:03:11Z",
  "branch": "mem0-integrate/remember-user-preferences",
  "product": "platform",
  "language": "python",
  "mem0_version": "2.0.0",
  "non_invasive": true,
  "feature_flag": "MEM0_ENABLED",
  "results": {
    "install":      {"status": "pass", "duration_ms": 12043},
    "static_checks":{"status": "pass", "duration_ms": 812},
    "unit_tests_flag_off": {"status": "pass", "duration_ms": 3920, "count": 47,
                            "reason": "all pre-existing tests green with flag unset"},
    "unit_tests_flag_on":  {"status": "pass", "duration_ms": 4321, "count": 49},
    "smoke_test":   {"status": "pass", "duration_ms": 2890, "memory_id": "mem_..."},
    "e2e_test":     {"status": "pass", "duration_ms": 14200,
                     "ready_probe_ms": 3100, "write_exit": 0,
                     "read_assert_matched": true}
  },
  "friction": {
    "dependency_install_retries": 0,
    "pre_existing_test_failures": 0,
    "warnings": ["mem0ai 2.0.0 pinned; consider 2.0.1 for fix X"]
  },
  "overall": "pass"
}

Markdown 版は人が読みやすい形式とし、以下を含めます。

  • ゴール文書と計画文書を冒頭に再掲します(レビュアーが探し回らずに済むようにします)。
  • 各チェックの合格/不合格とログ抜粋。
  • 問題点の概要。
  • mem0 SDK からの警告を逐語的に記載します(ある場合。例:非推奨フィールドの使用)。
  • 「NOT checked」セクションを明示的に設け、疎結合では検証できない項目を列挙します。 「保存されたデータがユーザーの望むものかどうか。検索が適切なタイミングで実行されるかどうか。user_id が実際のセッションスコープと一致するかどうか。人によるレビューが必要です。」
8. レポートと終了
  • スコアカードのパスと全体の合格/不合格を標準出力に表示します。
  • スコアカードファイルはコミットしないでください。 .mem0-integration/ 内に置かれ、gitignore 対象です。ユーザーは内容を確認し、必要に応じてピン留めできます。
  • 不合格の場合:最初に失敗したステップのログ末尾(最後の40行)を表示して終了します。修正は試みないでください。

成果物(すべて .mem0-integration/ 内)

ファイル用途保持期間
scorecard.md人が読める判定結果。実行ごとに上書き。
scorecard.json機械可読な判定結果。後で CI スコアカードワークフローが使用します。実行ごとに上書き。
test-stdout-flag-off.logステップ4 Pass A(既存のテストスイート、フラグ未設定)。実行ごとに上書き。
test-stdout-flag-on.logステップ4 Pass B(全テストスイート、フラグ設定済み)。実行ごとに上書き。
smoke-stdout.logステップ5の全出力。実行ごとに上書き。
e2e-app.logバックグラウンドアプリの標準出力/標準エラー(ステップ6)。実行ごとに上書き。
e2e-calls.logwrite_call と read_call の呼び出しおよび出力。実行ごとに上書き。

モード

モード条件動作
対話型(デフォルト)TTY があり、MEM0_TEST_CI が未設定不足しているキーを尋ね、わかりやすい概要を表示します。
CIMEM0_TEST_CI=1キーは環境変数に設定する必要があります。プロンプトは表示せず、失敗があればゼロ以外の終了コードを返します。ワークフローで解析できるよう、JSON スコアカードを標準出力の末尾に出力します。

実行方法

/mem0-test-integration                       # 対話型、すべてのステップ
/mem0-test-integration --ci                  # 非対話型
/mem0-test-integration --skip-smoke          # API 呼び出しなし、E2E なし
/mem0-test-integration --skip-e2e            # 単体テスト + スモークテストのみ(CI を高速化)
/mem0-test-integration --only-smoke          # スモークテストのみ
/mem0-test-integration --only-e2e            # E2E のみ(依存関係がインストール済みであることを前提とします)

組み合わせ:--skip-* は併用できます(--skip-smoke --skip-e2e = 静的チェック + 単体テストのみ、API コストなし)。--only-* は他のすべてのフラグと併用できません。

終了コード

コード意味
0すべてのチェックに合格しました。
1前提条件を満たしていません(.mem0-integration/ がない、ブランチが違う、作業ツリーに変更がある)。
2環境変数キーがない(CI モード)、または依存関係のインストールに失敗しました。
3静的健全性チェックに失敗しました(インポートが違う、型エラー)。
4単体テストに失敗しました(Pass B — 統合自体が壊れています)。
5スモークテストに失敗しました。
6E2E テストに失敗しました(ready_probe のタイムアウト、書き込み/読み取り呼び出しの失敗、または read_assert の不一致)。
7非侵襲性の違反:Pass A に失敗しました(既存のテストが壊れました)。インテグレーターの修復ループは、これに手を加えません。
8内部エラー(スキルの不具合です。報告してください)。

明示的に対象外の項目

  • ソースファイルの変更。 このスキルはリポジトリに対して読み取り専用です。 検証でバグが見つかった場合は、同じ目標と計画で /mem0-integrate を再実行してください。 手動で修正してはいけません。
  • 壊れたテストの修正。 単体テストの失敗は、テストが間違っているのではなく、 統合が間違っていることを示しています。このスキルは「別のテストを試す」ことはしません。
  • 論理的な正しさの深い検証。 E2E ステップでは、「ユーザーが以前に述べたことが後で返ってくる」ことを確認します。これは有用ですが、浅いシグナルです。 この統合が保存する適切な情報を選んでいるか、実際のユーザー間で user_id を正しくスコープしているか、競合解決を適切に処理しているかは証明しません。これらは人間によるレビューが必要です。
  • 自己修復。 このスキルがソースファイルを変更することはありません。対となる /mem0-integrate スキルは、デフォルトの --heal モードで、ここで生成されたスコアカードを読み取り、独自の修復ループを実行します。終了コード 7(非侵襲性の違反)は、修復ループが停止し、ユーザーに報告しなければならないことを明示するシグナルです。
  • ブランチ間の比較。 main を基準にした差分比較は行いません。スコアカードには、このブランチのみが反映されます。
  • 本番データに対する実行。 すべてのスモークテストでは、使い捨てのランダムな user_id を使用し、後でクリーンアップします。他のユーザーのデータには決して触れません。

コメント