feat(ci): gate pull requests on an accepted issue (#6894)
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
# Skills (`skills/`)
|
||||
|
||||
Claude Code skill definitions published from this repo. Agents fetch them by raw URL, so treat every file here as a public API.
|
||||
|
||||
## The two kinds
|
||||
|
||||
**Reference skills** carry SDK knowledge and are always available:
|
||||
|
||||
| Skill | Covers |
|
||||
|-------|--------|
|
||||
| `mem0/` | Python + TypeScript SDKs, Platform and OSS, framework integrations |
|
||||
| `mem0-cli/` | Terminal workflows for `mem0-cli` and `@mem0/cli` |
|
||||
| `mem0-vercel-ai-sdk/` | The `@mem0/vercel-ai-provider` package |
|
||||
|
||||
**Pipeline skills** run on demand and have side effects:
|
||||
|
||||
| Skill | Does |
|
||||
|-------|------|
|
||||
| `mem0-integrate/` | Wires Mem0 into an existing repo through a TDD pipeline. Writes a feature branch plus `.mem0-integration/` artifacts. |
|
||||
| `mem0-test-integration/` | Verifies what the integrator produced, on the same branch. Read-only against the repo. |
|
||||
| `mem0-oss-to-platform/` | Migrates a project from OSS to the hosted Platform SDK. Plans first, executes on approval. |
|
||||
|
||||
`mem0-integrate` and `mem0-test-integration` are **loosely coupled**: they share state only through `.mem0-integration/` files, never through conversation context.
|
||||
|
||||
## File layout
|
||||
|
||||
```
|
||||
skills/<name>/
|
||||
├── SKILL.md entry point, always loaded when the skill triggers
|
||||
├── README.md human-facing, GitHub renders this
|
||||
├── LICENSE Apache-2.0
|
||||
├── references/ loaded on demand, one file per topic
|
||||
├── client/ optional, per-runtime call patterns
|
||||
└── scripts/ optional executables
|
||||
```
|
||||
|
||||
## Size budget
|
||||
|
||||
`SKILL.md` is loaded in full every time the skill fires, so it is the expensive file. Keep it **under 500 lines**. Everything past the decision-making core belongs in `references/`, which the agent loads only when it needs that topic.
|
||||
|
||||
Rule of thumb for what stays in `SKILL.md`:
|
||||
|
||||
- Frontmatter, including the trigger and do-not-trigger conditions.
|
||||
- Anything the agent must honor on **every** run: non-negotiable principles, preconditions, gates.
|
||||
- A one-line-per-step overview of the pipeline.
|
||||
- Invocation, modes, exit codes.
|
||||
|
||||
Everything else, meaning full step mechanics, document templates, and verbatim subagent prompts, goes in `references/` with a link from the overview.
|
||||
|
||||
Current sizes, longest first:
|
||||
|
||||
```
|
||||
mem0/references/use-cases.md 720 reference, on demand
|
||||
mem0-cli/references/command-reference.md 694 reference, on demand
|
||||
mem0/client/python.md 487 reference, on demand
|
||||
mem0-integrate/references/pipeline.md 375 reference, on demand
|
||||
mem0-test-integration/SKILL.md 368 entry point, under budget
|
||||
mem0-integrate/SKILL.md 220 entry point
|
||||
mem0/SKILL.md 193 entry point
|
||||
mem0-vercel-ai-sdk/SKILL.md 192 entry point
|
||||
mem0-cli/SKILL.md 169 entry point
|
||||
mem0-oss-to-platform/SKILL.md 120 entry point
|
||||
```
|
||||
|
||||
`mem0-integrate` is the one skill that needed splitting: it was 620 lines, now
|
||||
220, with the ten-step mechanics in `references/pipeline.md` and the two
|
||||
verbatim subagent system prompts in `references/subagent-prompts.md`. The
|
||||
`SKILL.md` keeps only what every run must honor: canonical sources, the seven
|
||||
integration principles, the delegation table, preconditions, a one-line-per-step
|
||||
pipeline overview, artifacts, modes, invocation, and exit codes.
|
||||
|
||||
Reference files may run long. They are only read when the agent asks for that topic, so a 700-line `use-cases.md` costs nothing on a run that never opens it.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: <matches the directory name>
|
||||
description: >
|
||||
What it does, then TRIGGER when: ... then DO NOT TRIGGER when: ...
|
||||
The trigger conditions are what routing depends on. Be specific and
|
||||
name the sibling skill to use instead.
|
||||
license: Apache-2.0
|
||||
metadata:
|
||||
author: mem0ai
|
||||
version: "0.1.0"
|
||||
category: ai-memory
|
||||
tags: "comma, separated"
|
||||
mem0_tested_versions: "mem0ai (PyPI) >=2.0.0,<3.0.0; mem0ai (npm) >=3.0.0,<4.0.0"
|
||||
---
|
||||
```
|
||||
|
||||
Bump `mem0_tested_versions` whenever the SDK majors move. Skills that pin call shapes against a version that no longer exists produce code that fails at runtime, which is worse than a skill that declines to fire.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Cite canonical sources by URL (`https://docs.mem0.ai/llms.txt`, `openapi.json`, raw skill URLs). Skills must not rely on ambient model knowledge of the Mem0 API.
|
||||
- When one skill's territory is covered by another, delegate to it by raw URL rather than paraphrasing its patterns.
|
||||
- Pipeline skills declare **exit codes** in a table and mean them.
|
||||
- Cross-references between files use relative paths so the skill works when vendored into another repo.
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
AGENTS.md
|
||||
+14
-414
@@ -141,422 +141,22 @@ Exit with a written rationale if any precondition fails. Do not try to
|
||||
|
||||
## Pipeline
|
||||
|
||||
### 1. Language detection
|
||||
Ten steps. Full mechanics, document templates, and gate rules are in
|
||||
[`references/pipeline.md`](references/pipeline.md). Read that file when you
|
||||
start executing a step; the summary below is only for routing.
|
||||
|
||||
| Signal | Track |
|
||||
|---|---|
|
||||
| `package.json` + TypeScript config | Node / TypeScript |
|
||||
| `package.json` (no TS config) | Node / JavaScript |
|
||||
| `pyproject.toml` or `requirements.txt` | Python |
|
||||
|
||||
Monorepo with both → ask which subdirectory to operate in, then recurse.
|
||||
|
||||
### 2. Repo comprehension — what does this repo do, and where is the backend?
|
||||
|
||||
Before any decision (product, goal, plan), understand the repo enough
|
||||
to locate *where in the backend* the integration belongs. This is not
|
||||
fit-surveying — the user already decided Mem0 fits. This is mechanics:
|
||||
you cannot write a plan without knowing what files matter.
|
||||
|
||||
Read, in order, with a token budget — do not scan the whole tree:
|
||||
|
||||
1. `README.md` (root) + first-page of any `README_*.md` variants.
|
||||
2. `CONTRIBUTING.md` / `AGENTS.md` / `CLAUDE.md` at root if present —
|
||||
these often spell out architecture and entry points.
|
||||
3. `package.json` / `pyproject.toml` scripts + entry points.
|
||||
4. The layout of the top two directory levels (not recursive).
|
||||
5. Key config files: `docker-compose.yml`, `Dockerfile`, `Makefile`,
|
||||
`langgraph.json`, `next.config.*`, `nuxt.config.*`.
|
||||
|
||||
Produce `.mem0-integration/repo-summary.md`:
|
||||
|
||||
# Repo comprehension
|
||||
|
||||
**What this repo does:** <one paragraph in plain English. Who is
|
||||
the end user? What does the app do for them? What LLM / agent
|
||||
behavior is central? Do not list dependencies — describe behavior.>
|
||||
|
||||
**Architecture at a glance:**
|
||||
- Backend: <path(s), framework, primary entry point>
|
||||
- Frontend: <path(s) if any, framework — for context only; no
|
||||
integration here>
|
||||
- Agent loop / orchestration: <LangGraph? custom? none?>
|
||||
- Existing memory/session/state systems: <name them — these are
|
||||
what step 6 Coexistence must preserve>
|
||||
|
||||
**Candidate backend integration surfaces** (ranked, best first):
|
||||
1. `<backend-file>:<line_range>` — <function> — <one-sentence
|
||||
reason this is where write/read could slot in without
|
||||
replacing anything existing>
|
||||
2. ...
|
||||
3. ...
|
||||
|
||||
**Not a fit here:** <list anything the skill considered but ruled
|
||||
out — e.g., "frontend chat component: client-side, excluded by
|
||||
backend-only rule"; "existing memory subsystem X: would require
|
||||
replacement, excluded by additive principle">
|
||||
|
||||
**Sources read:** <list the files actually opened, with line counts,
|
||||
so reviewers can verify coverage.>
|
||||
|
||||
Show the user the rendered summary and ask: *"Is this understanding
|
||||
correct? Which of the candidate surfaces (1, 2, 3 ...) should step 3
|
||||
forward target?"*
|
||||
|
||||
Gate rules:
|
||||
|
||||
- If no backend surface is found → exit code 1. The preconditions
|
||||
should already have caught frontend-only repos; reaching this point
|
||||
means a more subtle miss (e.g., the "backend" is actually just a
|
||||
static build). Do not force a fit.
|
||||
- If every candidate surface would require replacing an existing
|
||||
memory/session system → exit code 1 with the "additive principle"
|
||||
rationale. The user can manually point at a non-conflicting location
|
||||
and re-run.
|
||||
- User corrections update `repo-summary.md` and re-confirm. Max 3
|
||||
rounds; beyond that, exit code 1.
|
||||
|
||||
The user's chosen surface index is baked into `product.json` as
|
||||
`preferred_site` and referenced by steps 5 and 6.
|
||||
|
||||
### 3. Product selection — Platform vs OSS (ask with a recommendation)
|
||||
|
||||
Read the `## Identify the User's Setup` block in
|
||||
`https://docs.mem0.ai/llms.txt` for the Platform-first routing rules, then
|
||||
apply the heuristics below. Ask, but never blank:
|
||||
|
||||
- Other managed-service SDKs present (`@clerk/*`, `stripe`, `@supabase/*`,
|
||||
`openai`, `@upstash/*`, `posthog-*`) — 3+ → recommend **Platform**.
|
||||
- Local-infra signals (`docker-compose.yml` with postgres / redis / qdrant /
|
||||
neo4j, ollama configs, self-hosted auth) — 2+ → recommend **OSS**.
|
||||
- No strong signal → default recommendation: **Platform** (lower integration
|
||||
cost; migration later is supported).
|
||||
|
||||
Example:
|
||||
|
||||
> I see `stripe`, `@clerk/nextjs`, and `@supabase/supabase-js` — managed
|
||||
> services throughout. I recommend **Mem0 Platform** (4-line integration).
|
||||
> Override and use open source?
|
||||
|
||||
Bake the choice into the goal doc in step 5. Do not re-decide later.
|
||||
|
||||
### 4. API key check (env-first, then ask)
|
||||
|
||||
| Track | Key | Where to find |
|
||||
| # | Step | Gate |
|
||||
|---|---|---|
|
||||
| Platform | `MEM0_API_KEY` | https://app.mem0.ai |
|
||||
| OSS (default LLM) | `OPENAI_API_KEY` | https://platform.openai.com/api-keys |
|
||||
|
||||
If present in env → continue.
|
||||
If `MEM0_API_KEY` is missing AND the track is **Platform** → **default to Agent Mode**: run `mem0 init --agent --agent-caller <your-name> --json` (after `pip install mem0-cli` or `npm install -g @mem0/cli`), substituting your agent identity (e.g. `claude-code`, `cursor`, `codex`). If you forgot to pass `--agent-caller`, run `mem0 identify <your-name>` after init. Cache the key to `.env` (with user consent) and continue. Tell the user to claim later with `mem0 init --email <their-email>` — same key, no agent disruption.
|
||||
If missing AND **CI mode** (`MEM0_INTEGRATE_CI=1`) → exit with code 2 and the name of the missing key.
|
||||
|
||||
Never echo key values into `trace.jsonl`. Persist to `.env` only with
|
||||
explicit user consent, and append `.env` to `.gitignore` if not already there.
|
||||
|
||||
If the user is on OSS and wants a non-OpenAI LLM, route them to the
|
||||
`components/llms/*` docs and re-run this step with the chosen provider's key.
|
||||
|
||||
### 5. Goal doc — the hard gate
|
||||
|
||||
Write `.mem0-integration/goal.md` and **require user approval before step 6**.
|
||||
|
||||
Template:
|
||||
|
||||
# Mem0 Integration Goal
|
||||
|
||||
**What gets stored:** <one sentence — user utterances? extracted
|
||||
preferences? a specific domain fact like "dietary restrictions"?>
|
||||
|
||||
**When it gets retrieved:** <one sentence — on each user turn? before a
|
||||
specific tool call? at session start?>
|
||||
|
||||
**Why:** <one sentence — the user-visible behavior change. "Assistant
|
||||
remembers previous orders across sessions," not "we added memory.">
|
||||
|
||||
**Product:** Platform | OSS (locked from step 3, do not change)
|
||||
|
||||
**Delegated skill:** <raw URL of the published skill being used
|
||||
from "Skill delegation rules" above, or "none — custom integration
|
||||
against `skills/mem0`">.
|
||||
|
||||
**Out of scope:** <anything explicitly excluded: "no graph memory,"
|
||||
"no multimodal," "no migration from existing store">
|
||||
|
||||
Rules:
|
||||
|
||||
- User must approve explicitly. If they edit the doc, reload and re-confirm.
|
||||
- `goal.md` is the contract the test suite is written against. Never
|
||||
rewrite it after step 6 starts.
|
||||
- Max 3 rejection rounds. On the 4th, exit with code 3 and the rejection
|
||||
notes — the integration is not well-specified enough to proceed.
|
||||
|
||||
### 6. Integration plan — how and where (hard gate)
|
||||
|
||||
Given `goal.md` is "what and why," this step produces "where and how" and
|
||||
gets explicit user sign-off before any code is written.
|
||||
|
||||
The skill does a **scoped** read of the repo (no wide survey):
|
||||
|
||||
- Grep for the LLM call sites that match the goal (e.g., `openai.chat.`,
|
||||
`anthropic.messages.`, `model.generateContent`, `ChatOpenAI`, `createLLM`).
|
||||
- Grep for the user-identity source (`req.user`, `session.user`, `auth()`,
|
||||
`ctx.userId`, cookies).
|
||||
- Check `package.json` / `pyproject.toml` / `requirements.txt` for
|
||||
conflicts (e.g., existing `mem0ai` at a different version).
|
||||
|
||||
Then write `.mem0-integration/plan.md`:
|
||||
|
||||
# Mem0 Integration Plan
|
||||
|
||||
**Write pattern:** <one sentence — e.g., "After each assistant reply,
|
||||
call client.add([user_msg, assistant_msg], user_id=<source>).">
|
||||
|
||||
**Read pattern:** <one sentence — e.g., "Before building the LLM prompt,
|
||||
call client.search(query=latest_user_msg, user_id=<source>, limit=5)
|
||||
and inject results as a system message.">
|
||||
|
||||
**User identifier source:** <code path — e.g., `req.auth.userId`,
|
||||
`session.user.email`, `ctx.params.user_id`. If none, ask the user.>
|
||||
|
||||
**Session scoping:**
|
||||
- user_id: <source>
|
||||
- agent_id: <static slug | null>
|
||||
- run_id: <source | null>
|
||||
|
||||
**Write call site:** `<file:line_range>` — inside `<function>`
|
||||
**Read call site:** `<file:line_range>` — inside `<function>`
|
||||
|
||||
**Dependencies to add:**
|
||||
- `<package>@<version pinned in frontmatter>`
|
||||
|
||||
**Preserved behavior:** <list the existing repo behaviors that must
|
||||
keep working after this edit — e.g., "existing OpenAI streaming still
|
||||
works," "existing Redis session store still used," "existing tests
|
||||
still pass unchanged.">
|
||||
|
||||
**Coexistence:** <one bullet per existing system the integration sits
|
||||
alongside. Name the files/classes. Example: "The existing
|
||||
`agents/memory/storage.py` MemoryStorage class remains untouched and
|
||||
keeps its LangGraph SummarizationEvent flow. Mem0 is added as a
|
||||
parallel long-term-facts store, in a new file, invoked only when
|
||||
MEM0_ENABLED=1 is set.">
|
||||
|
||||
**Feature flag:** <the exact mechanism and the default. Required.
|
||||
Example: `env MEM0_ENABLED=1`, default unset / off; `config.mem0.enabled`,
|
||||
default false. With the flag in its default state, the repo must
|
||||
behave exactly like `main`.>
|
||||
|
||||
**Sources consulted:** <minimum 2 URLs from "Canonical sources" above
|
||||
that informed this plan. At least one `docs.mem0.ai` URL and one
|
||||
delegated-skill URL. Cite the specific section or heading.>
|
||||
|
||||
**E2E recipe:** <how the verification skill should drive the app
|
||||
end-to-end. Omit only if the repo is a pure library with no runnable
|
||||
entry point — in which case the E2E step will skip with a warning.>
|
||||
|
||||
start: <shell command to launch the app locally,
|
||||
using $PORT for any network port>
|
||||
ready_probe: <one of: url=<URL> status=<code> /
|
||||
log="<substring to wait for>" /
|
||||
sleep=<seconds, last resort>>
|
||||
compose_services: <optional: whitespace-separated service
|
||||
names in docker-compose.yml to start first;
|
||||
use label mem0-e2e: "true" to mark them>
|
||||
write_call: <command that triggers the Mem0 write path
|
||||
exactly once; ≤ 60s runtime>
|
||||
write_async_wait_ms: <milliseconds to wait after write_call for
|
||||
async memory flush; default 0>
|
||||
read_call: <command that triggers the Mem0 read path,
|
||||
typically a fresh session / new request>
|
||||
read_assert: <substring, regex, or jsonpath=<expr>=<value>
|
||||
that MUST appear in read_call's output for
|
||||
the E2E to pass. Derived from goal.md's
|
||||
"What gets stored.">
|
||||
|
||||
**Rejected alternatives:** <briefly, 1–2 bullets — patterns the skill
|
||||
considered but did not pick, and why. Helps the user decide.>
|
||||
|
||||
Rules:
|
||||
|
||||
- Show the user the proposed call sites with 10 lines of context around
|
||||
each before asking for approval.
|
||||
- If the skill can't find a plausible call site for either write or read,
|
||||
it exits with code 5 and asks the user to name the file(s) manually
|
||||
(this is the "no fit here" signal — don't guess).
|
||||
- Max 3 rejection rounds on the plan. On the 4th, exit code 5 with the
|
||||
last plan and the user's notes.
|
||||
- If the user edits `plan.md` by hand, reload and re-confirm.
|
||||
|
||||
`plan.md` (not `goal.md`) is the contract the subagent implements against
|
||||
in step 8.
|
||||
|
||||
### 7. Tests first (TDD)
|
||||
|
||||
Main agent writes failing tests against `goal.md` in the repo's native
|
||||
test framework:
|
||||
|
||||
| Track | Default framework |
|
||||
|---|---|
|
||||
| Python | `pytest` |
|
||||
| TypeScript | `vitest` if detected, else `jest` |
|
||||
| JavaScript | same |
|
||||
|
||||
Test assertion shapes must match the **canonical signatures**:
|
||||
|
||||
- Platform method signatures: `https://docs.mem0.ai/openapi.json`
|
||||
(request body schemas for `/v1/memories/` and `/v1/memories/search/`).
|
||||
- OSS method signatures: the delegated skill named in `plan.md`
|
||||
(fetched from its raw URL) or `skills/mem0/SKILL.md` as the default.
|
||||
- Do not hand-roll request shapes. If the delegated skill has an
|
||||
example block, lift it verbatim.
|
||||
|
||||
Minimum two test files (paths taken from `plan.md` call sites):
|
||||
|
||||
- `test_mem0_write.<ext>` — asserts `add()` is called at the Write call
|
||||
site with the right payload shape (Platform messages-array vs OSS string)
|
||||
and the right `user_id` source.
|
||||
- `test_mem0_read.<ext>` — asserts `search()` runs before the Read call
|
||||
site and the result is wired into the LLM prompt / response path.
|
||||
|
||||
Tests MUST be importable with `MEM0_API_KEY` unset. This is the design
|
||||
pressure that forces step 8's lazy `MemoryClient()` / `Memory()`
|
||||
construction — eager module-level init hits the API on import and
|
||||
breaks pre-existing test collection when the key is missing.
|
||||
|
||||
Run the tests. They **must fail**. If they pass before any implementation,
|
||||
the tests are wrong — rewrite them.
|
||||
|
||||
### 8. Implementation (subagent, fresh context)
|
||||
|
||||
Spawn a subagent with:
|
||||
|
||||
- **Inputs**: the repo, `goal.md`, `plan.md`, the two test files, and
|
||||
direct URLs to: the delegated skill (from `plan.md`), the SDK source
|
||||
(pinned per `mem0_tested_versions`), `https://docs.mem0.ai/llms.txt`,
|
||||
and `https://docs.mem0.ai/openapi.json`.
|
||||
- **No access** to main agent's reasoning trace or scratchpad.
|
||||
- **System prompt** (verbatim):
|
||||
|
||||
You are implementing a Mem0 integration for an existing repo.
|
||||
|
||||
Read these first:
|
||||
- plan.md (the mechanical contract)
|
||||
- goal.md (the intent — do not change it)
|
||||
- the test files (do not change them either)
|
||||
- <delegated skill raw URL from plan.md>
|
||||
- https://docs.mem0.ai/llms.txt
|
||||
- https://docs.mem0.ai/openapi.json (Platform only)
|
||||
|
||||
Constraints — all required, all enforced at review:
|
||||
|
||||
1. Touch only the files named in plan.md's call sites, or add
|
||||
strictly new files.
|
||||
2. Do not remove or rename any existing symbol. Do not change
|
||||
any public signature.
|
||||
3. Do not modify any existing test.
|
||||
4. Gate every line of new Mem0 code behind the feature flag from
|
||||
plan.md. With the flag in its default state, the repo must
|
||||
behave exactly like `main` — byte-for-byte, including stdout
|
||||
and return values.
|
||||
5. Use only the <Platform | OSS> SDK surface. No new dependencies
|
||||
beyond those listed under plan.md's "Dependencies to add."
|
||||
6. Preserve everything listed under plan.md's "Preserved behavior"
|
||||
and "Coexistence."
|
||||
7. Lazy client construction. `MemoryClient()` validates the API
|
||||
key in `__init__` (it makes a network call). Never instantiate
|
||||
it at module-import time — construct on first use inside the
|
||||
request / handler path. The same rule applies to OSS `Memory()`,
|
||||
which can eagerly initialize embedding and LLM providers. Use
|
||||
a function-local singleton (`functools.lru_cache`, a module-level
|
||||
`_client = None` + getter, or DI scope) — never a top-level
|
||||
global. Eager init breaks the pre-existing test suite at
|
||||
collection time whenever the key is missing or invalid, which
|
||||
is a non-invasiveness violation.
|
||||
|
||||
Implement the plan to make the new tests pass while all
|
||||
pre-existing tests continue to pass unchanged.
|
||||
|
||||
Subagent returns a diff. Main agent reviews against `plan.md` (the
|
||||
mechanical contract) and `goal.md` (the intent):
|
||||
|
||||
- Approved → apply the diff, commit.
|
||||
- Rejected → return with specific, actionable feedback (not "try again").
|
||||
- Max 3 review loops. Beyond that → exit code 4 with the last diff and
|
||||
reviewer feedback.
|
||||
|
||||
### 9. Commit + handoff
|
||||
|
||||
Create branch `mem0-integrate/<short-goal-slug>` and commit in
|
||||
**separate commits** so reviewers can cherry-pick:
|
||||
|
||||
1. `mem0: add gated dependency` — just the `pyproject.toml` / `package.json`
|
||||
change.
|
||||
2. `mem0: add integration module` — the new file(s).
|
||||
3. `mem0: wire into <call site>` — the call-site edit(s), still gated.
|
||||
4. `mem0: add tests` — the new test files.
|
||||
|
||||
If `--no-heal` is set → print `Run /mem0-test-integration to verify.`
|
||||
and exit. Otherwise proceed to step 10.
|
||||
|
||||
### 10. Self-healing loop (default ON; disable with `--no-heal`)
|
||||
|
||||
Run `/mem0-test-integration --ci` in a subprocess. If `scorecard.json`
|
||||
reports `overall: pass` → done, exit 0.
|
||||
|
||||
Otherwise loop:
|
||||
|
||||
1. **Categorize the failing check** from `scorecard.json`. Route per
|
||||
category:
|
||||
- `install` / `static_checks` → dependency or import fix.
|
||||
- `unit_tests` → wiring or assertion fix.
|
||||
- `smoke_test` → API key or SDK call-shape fix.
|
||||
- `e2e_test` → recipe, flag-wiring, or integration-point fix.
|
||||
- **Pre-existing test failure (test skill exit code 7,
|
||||
`non_invasive: false` in scorecard) → STOP.** This is a
|
||||
non-invasiveness violation. Do NOT attempt to "fix" it (that
|
||||
breaks principle 3). Exit code 6 with rationale.
|
||||
|
||||
2. **Spawn a remediation subagent**, fresh context. Inputs:
|
||||
`plan.md`, `goal.md`, `scorecard.md`, `scorecard.json`, the last
|
||||
committed diff, and the relevant log file for the failing category
|
||||
(`test-stdout.log` / `smoke-stdout.log` / `e2e-app.log` /
|
||||
`e2e-calls.log`).
|
||||
|
||||
System prompt (verbatim):
|
||||
|
||||
You are fixing a failing Mem0 integration test.
|
||||
|
||||
Non-negotiable constraints:
|
||||
- Do not modify test files.
|
||||
- Do not remove or rename any existing symbol or signature.
|
||||
- Do not change pre-existing behavior. The feature flag from
|
||||
plan.md must still default to OFF, and with the flag in its
|
||||
default state the repo must behave exactly like main.
|
||||
- Touch only the files named in plan.md's call sites, or add
|
||||
strictly new files.
|
||||
- Return the smallest possible diff that fixes the single
|
||||
failing check listed in scorecard.md. No drive-by cleanup.
|
||||
|
||||
3. **Apply the diff**; commit on the same branch with message
|
||||
`mem0-heal: <category> attempt <N>`. Do NOT amend earlier commits
|
||||
(reviewers need the heal trail).
|
||||
|
||||
4. **Re-run `/mem0-test-integration --ci`**. Outcomes:
|
||||
- `overall: pass` → done, exit 0.
|
||||
- Same check still failing → increment attempt counter; loop.
|
||||
- A *different* check now failing → regression. Revert the heal
|
||||
commit (`git revert HEAD --no-edit`), record the regression in
|
||||
`.mem0-integration/heal-trace.md`, exit code 6.
|
||||
|
||||
5. **Bounded iterations.** Default 3 attempts per failing category.
|
||||
Override with `--heal-max N` (hard cap 10). On exhaustion, exit 6
|
||||
with the full attempt trace: each diff, each scorecard, final log
|
||||
tail.
|
||||
|
||||
6. **Post-loop summary** written to `.mem0-integration/heal-trace.md`:
|
||||
which category failed, how many attempts, each diff's intent, final
|
||||
status, and — on success — the delta from initial scorecard to final.
|
||||
| 1 | **Language detection.** `package.json` / `pyproject.toml` / `requirements.txt`. Monorepo, ask which subdirectory. | |
|
||||
| 2 | **Repo comprehension.** Budgeted read of README, contributor docs, entry points, top two directory levels. Produces `repo-summary.md` with ranked backend surfaces. | User confirms the summary and picks a surface. No backend surface, exit 1. |
|
||||
| 3 | **Product selection.** Platform vs OSS, recommended from dependency signals, never asked blank. | Locked into `goal.md`, never re-decided. |
|
||||
| 4 | **API key check.** `MEM0_API_KEY` (Platform) or `OPENAI_API_KEY` (OSS). Missing on Platform, default to Agent Mode via `mem0 init --agent`. | CI mode with a missing key, exit 2. |
|
||||
| 5 | **Goal doc.** `goal.md`: what gets stored, when it is retrieved, why, product, delegated skill, out of scope. | **Hard gate.** Explicit approval required. 3 rejections, exit 3. |
|
||||
| 6 | **Integration plan.** Scoped grep for call sites and identity source. `plan.md`: write/read patterns, scoping, call sites, dependencies, preserved behavior, coexistence, feature flag, sources, E2E recipe. | **Hard gate.** No plausible additive call site or 3 rejections, exit 5. |
|
||||
| 7 | **Tests first.** Failing write and read tests in the repo's native framework, assertion shapes lifted from the canonical signatures. Must be importable with `MEM0_API_KEY` unset. | Tests must fail. If they pass, they are wrong. |
|
||||
| 8 | **Implementation.** Fresh-context subagent, prompt in [`references/subagent-prompts.md`](references/subagent-prompts.md), returns a diff reviewed against `plan.md` and `goal.md`. | 3 review loops, then exit 4. |
|
||||
| 9 | **Commit and handoff.** Branch `mem0-integrate/<slug>`, four separable commits: dependency, module, wiring, tests. | `--no-heal` stops here. |
|
||||
| 10 | **Self-healing loop.** Runs `/mem0-test-integration --ci`, categorizes the failure, spawns a bounded remediation subagent, reverts on regression. | Pre-existing test failure, **stop**, exit 6. Never "fix" it. |
|
||||
|
||||
## Artifacts (all under `.mem0-integration/`)
|
||||
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
# Pipeline mechanics
|
||||
|
||||
Full step-by-step for `mem0-integrate`. Read this when you are executing a
|
||||
step. The one-line-per-step overview and every non-negotiable rule live in
|
||||
`../SKILL.md`, which is loaded on every run; this file is loaded on demand.
|
||||
|
||||
Verbatim subagent system prompts for steps 8 and 10 are in
|
||||
[`subagent-prompts.md`](subagent-prompts.md).
|
||||
|
||||
## 1. Language detection
|
||||
|
||||
| Signal | Track |
|
||||
|---|---|
|
||||
| `package.json` + TypeScript config | Node / TypeScript |
|
||||
| `package.json` (no TS config) | Node / JavaScript |
|
||||
| `pyproject.toml` or `requirements.txt` | Python |
|
||||
|
||||
Monorepo with both, ask which subdirectory to operate in, then recurse.
|
||||
|
||||
## 2. Repo comprehension: what does this repo do, and where is the backend?
|
||||
|
||||
Before any decision (product, goal, plan), understand the repo enough to
|
||||
locate *where in the backend* the integration belongs. This is not
|
||||
fit-surveying, the user already decided Mem0 fits. This is mechanics: you
|
||||
cannot write a plan without knowing what files matter.
|
||||
|
||||
Read, in order, with a token budget. Do not scan the whole tree.
|
||||
|
||||
1. `README.md` (root) plus the first page of any `README_*.md` variants.
|
||||
2. `CONTRIBUTING.md` / `AGENTS.md` / `CLAUDE.md` at root if present. These
|
||||
often spell out architecture and entry points.
|
||||
3. `package.json` / `pyproject.toml` scripts and entry points.
|
||||
4. The layout of the top two directory levels, not recursive.
|
||||
5. Key config files: `docker-compose.yml`, `Dockerfile`, `Makefile`,
|
||||
`langgraph.json`, `next.config.*`, `nuxt.config.*`.
|
||||
|
||||
Produce `.mem0-integration/repo-summary.md`:
|
||||
|
||||
# Repo comprehension
|
||||
|
||||
**What this repo does:** <one paragraph in plain English. Who is
|
||||
the end user? What does the app do for them? What LLM / agent
|
||||
behavior is central? Do not list dependencies, describe behavior.>
|
||||
|
||||
**Architecture at a glance:**
|
||||
- Backend: <path(s), framework, primary entry point>
|
||||
- Frontend: <path(s) if any, framework, for context only; no
|
||||
integration here>
|
||||
- Agent loop / orchestration: <LangGraph? custom? none?>
|
||||
- Existing memory/session/state systems: <name them, these are
|
||||
what step 6 Coexistence must preserve>
|
||||
|
||||
**Candidate backend integration surfaces** (ranked, best first):
|
||||
1. `<backend-file>:<line_range>` <function> <one-sentence
|
||||
reason this is where write/read could slot in without
|
||||
replacing anything existing>
|
||||
2. ...
|
||||
3. ...
|
||||
|
||||
**Not a fit here:** <list anything the skill considered but ruled
|
||||
out, e.g. "frontend chat component: client-side, excluded by
|
||||
backend-only rule"; "existing memory subsystem X: would require
|
||||
replacement, excluded by additive principle">
|
||||
|
||||
**Sources read:** <list the files actually opened, with line counts,
|
||||
so reviewers can verify coverage.>
|
||||
|
||||
Show the user the rendered summary and ask: *"Is this understanding correct?
|
||||
Which of the candidate surfaces (1, 2, 3 ...) should step 3 forward target?"*
|
||||
|
||||
Gate rules:
|
||||
|
||||
- No backend surface found, exit code 1. Preconditions should already have
|
||||
caught frontend-only repos; reaching this point means a subtler miss (for
|
||||
example the "backend" is actually just a static build). Do not force a fit.
|
||||
- Every candidate surface would require replacing an existing memory or
|
||||
session system, exit code 1 with the additive-principle rationale. The user
|
||||
can point at a non-conflicting location manually and re-run.
|
||||
- User corrections update `repo-summary.md` and re-confirm. Max 3 rounds,
|
||||
beyond that exit code 1.
|
||||
|
||||
The user's chosen surface index is baked into `product.json` as
|
||||
`preferred_site` and referenced by steps 5 and 6.
|
||||
|
||||
## 3. Product selection: Platform vs OSS
|
||||
|
||||
Read the `## Identify the User's Setup` block in
|
||||
`https://docs.mem0.ai/llms.txt` for the Platform-first routing rules, then
|
||||
apply the heuristics below. Ask, but never blank.
|
||||
|
||||
- Other managed-service SDKs present (`@clerk/*`, `stripe`, `@supabase/*`,
|
||||
`openai`, `@upstash/*`, `posthog-*`), 3 or more, recommend **Platform**.
|
||||
- Local-infra signals (`docker-compose.yml` with postgres / redis / qdrant /
|
||||
neo4j, ollama configs, self-hosted auth), 2 or more, recommend **OSS**.
|
||||
- No strong signal, default recommendation **Platform**: lower integration
|
||||
cost, and migration later is supported.
|
||||
|
||||
Example:
|
||||
|
||||
> I see `stripe`, `@clerk/nextjs`, and `@supabase/supabase-js`, managed
|
||||
> services throughout. I recommend **Mem0 Platform** (4-line integration).
|
||||
> Override and use open source?
|
||||
|
||||
Bake the choice into the goal doc in step 5. Do not re-decide later.
|
||||
|
||||
## 4. API key check (env first, then ask)
|
||||
|
||||
| Track | Key | Where to find |
|
||||
|---|---|---|
|
||||
| Platform | `MEM0_API_KEY` | https://app.mem0.ai |
|
||||
| OSS (default LLM) | `OPENAI_API_KEY` | https://platform.openai.com/api-keys |
|
||||
|
||||
Present in env, continue.
|
||||
|
||||
`MEM0_API_KEY` missing and the track is **Platform**, **default to Agent
|
||||
Mode**: run `mem0 init --agent --agent-caller <your-name> --json` (after
|
||||
`pip install mem0-cli` or `npm install -g @mem0/cli`), substituting your agent
|
||||
identity such as `claude-code`, `cursor`, `codex`. If you forgot
|
||||
`--agent-caller`, run `mem0 identify <your-name>` after init. Cache the key to
|
||||
`.env` with user consent and continue. Tell the user to claim it later with
|
||||
`mem0 init --email <their-email>`: same key, no agent disruption.
|
||||
|
||||
Missing and **CI mode** (`MEM0_INTEGRATE_CI=1`), exit code 2 with the name of
|
||||
the missing key.
|
||||
|
||||
Never echo key values into `trace.jsonl`. Persist to `.env` only with explicit
|
||||
user consent, and append `.env` to `.gitignore` if it is not there already.
|
||||
|
||||
If the user is on OSS and wants a non-OpenAI LLM, route them to the
|
||||
`components/llms/*` docs and re-run this step with the chosen provider's key.
|
||||
|
||||
## 5. Goal doc, the hard gate
|
||||
|
||||
Write `.mem0-integration/goal.md` and **require user approval before step 6**.
|
||||
|
||||
# Mem0 Integration Goal
|
||||
|
||||
**What gets stored:** <one sentence. User utterances? Extracted
|
||||
preferences? A specific domain fact like "dietary restrictions"?>
|
||||
|
||||
**When it gets retrieved:** <one sentence. On each user turn? Before a
|
||||
specific tool call? At session start?>
|
||||
|
||||
**Why:** <one sentence, the user-visible behavior change. "Assistant
|
||||
remembers previous orders across sessions," not "we added memory.">
|
||||
|
||||
**Product:** Platform | OSS (locked from step 3, do not change)
|
||||
|
||||
**Delegated skill:** <raw URL of the published skill being used
|
||||
from the delegation table in SKILL.md, or "none, custom integration
|
||||
against `skills/mem0`">.
|
||||
|
||||
**Out of scope:** <anything explicitly excluded: "no graph memory,"
|
||||
"no multimodal," "no migration from existing store">
|
||||
|
||||
Rules:
|
||||
|
||||
- The user must approve explicitly. If they edit the doc, reload and
|
||||
re-confirm.
|
||||
- `goal.md` is the contract the test suite is written against. Never rewrite
|
||||
it after step 6 starts.
|
||||
- Max 3 rejection rounds. On the 4th, exit code 3 with the rejection notes:
|
||||
the integration is not well-specified enough to proceed.
|
||||
|
||||
## 6. Integration plan, where and how (hard gate)
|
||||
|
||||
`goal.md` is what and why. This step produces where and how, and gets explicit
|
||||
sign-off before any code is written.
|
||||
|
||||
Do a **scoped** read of the repo, no wide survey:
|
||||
|
||||
- Grep for the LLM call sites that match the goal (`openai.chat.`,
|
||||
`anthropic.messages.`, `model.generateContent`, `ChatOpenAI`, `createLLM`).
|
||||
- Grep for the user-identity source (`req.user`, `session.user`, `auth()`,
|
||||
`ctx.userId`, cookies).
|
||||
- Check `package.json` / `pyproject.toml` / `requirements.txt` for conflicts,
|
||||
for example an existing `mem0ai` at a different version.
|
||||
|
||||
Then write `.mem0-integration/plan.md`:
|
||||
|
||||
# Mem0 Integration Plan
|
||||
|
||||
**Write pattern:** <one sentence, e.g. "After each assistant reply,
|
||||
call client.add([user_msg, assistant_msg], user_id=<source>).">
|
||||
|
||||
**Read pattern:** <one sentence, e.g. "Before building the LLM prompt,
|
||||
call client.search(query=latest_user_msg, user_id=<source>, limit=5)
|
||||
and inject results as a system message.">
|
||||
|
||||
**User identifier source:** <code path, e.g. `req.auth.userId`,
|
||||
`session.user.email`, `ctx.params.user_id`. If none, ask the user.>
|
||||
|
||||
**Session scoping:**
|
||||
- user_id: <source>
|
||||
- agent_id: <static slug | null>
|
||||
- run_id: <source | null>
|
||||
|
||||
**Write call site:** `<file:line_range>` inside `<function>`
|
||||
**Read call site:** `<file:line_range>` inside `<function>`
|
||||
|
||||
**Dependencies to add:**
|
||||
- `<package>@<version pinned in frontmatter>`
|
||||
|
||||
**Preserved behavior:** <list the existing repo behaviors that must
|
||||
keep working after this edit, e.g. "existing OpenAI streaming still
|
||||
works," "existing Redis session store still used," "existing tests
|
||||
still pass unchanged.">
|
||||
|
||||
**Coexistence:** <one bullet per existing system the integration sits
|
||||
alongside. Name the files/classes. Example: "The existing
|
||||
`agents/memory/storage.py` MemoryStorage class remains untouched and
|
||||
keeps its LangGraph SummarizationEvent flow. Mem0 is added as a
|
||||
parallel long-term-facts store, in a new file, invoked only when
|
||||
MEM0_ENABLED=1 is set.">
|
||||
|
||||
**Feature flag:** <the exact mechanism and the default. Required.
|
||||
Example: `env MEM0_ENABLED=1`, default unset / off; `config.mem0.enabled`,
|
||||
default false. With the flag in its default state, the repo must
|
||||
behave exactly like `main`.>
|
||||
|
||||
**Sources consulted:** <minimum 2 URLs from "Canonical sources" in
|
||||
SKILL.md that informed this plan. At least one `docs.mem0.ai` URL and
|
||||
one delegated-skill URL. Cite the specific section or heading.>
|
||||
|
||||
**E2E recipe:** <how the verification skill should drive the app
|
||||
end-to-end. Omit only if the repo is a pure library with no runnable
|
||||
entry point, in which case the E2E step skips with a warning.>
|
||||
|
||||
start: <shell command to launch the app locally,
|
||||
using $PORT for any network port>
|
||||
ready_probe: <one of: url=<URL> status=<code> /
|
||||
log="<substring to wait for>" /
|
||||
sleep=<seconds, last resort>>
|
||||
compose_services: <optional: whitespace-separated service
|
||||
names in docker-compose.yml to start first;
|
||||
use label mem0-e2e: "true" to mark them>
|
||||
write_call: <command that triggers the Mem0 write path
|
||||
exactly once; 60s runtime or less>
|
||||
write_async_wait_ms: <milliseconds to wait after write_call for
|
||||
async memory flush; default 0>
|
||||
read_call: <command that triggers the Mem0 read path,
|
||||
typically a fresh session / new request>
|
||||
read_assert: <substring, regex, or jsonpath=<expr>=<value>
|
||||
that MUST appear in read_call's output for
|
||||
the E2E to pass. Derived from goal.md's
|
||||
"What gets stored.">
|
||||
|
||||
**Rejected alternatives:** <briefly, 1 or 2 bullets. Patterns the skill
|
||||
considered but did not pick, and why. Helps the user decide.>
|
||||
|
||||
Rules:
|
||||
|
||||
- Show the user the proposed call sites with 10 lines of context around each
|
||||
before asking for approval.
|
||||
- If no plausible call site exists for either write or read, exit code 5 and
|
||||
ask the user to name the files manually. That is the "no fit here" signal,
|
||||
do not guess.
|
||||
- Max 3 rejection rounds on the plan. On the 4th, exit code 5 with the last
|
||||
plan and the user's notes.
|
||||
- If the user edits `plan.md` by hand, reload and re-confirm.
|
||||
|
||||
`plan.md`, not `goal.md`, is the contract the subagent implements against in
|
||||
step 8.
|
||||
|
||||
## 7. Tests first (TDD)
|
||||
|
||||
The main agent writes failing tests against `goal.md` in the repo's native
|
||||
test framework:
|
||||
|
||||
| Track | Default framework |
|
||||
|---|---|
|
||||
| Python | `pytest` |
|
||||
| TypeScript | `vitest` if detected, else `jest` |
|
||||
| JavaScript | same |
|
||||
|
||||
Test assertion shapes must match the **canonical signatures**:
|
||||
|
||||
- Platform method signatures: `https://docs.mem0.ai/openapi.json`, the request
|
||||
body schemas for `/v1/memories/` and `/v1/memories/search/`.
|
||||
- OSS method signatures: the delegated skill named in `plan.md` (fetched from
|
||||
its raw URL), or `skills/mem0/SKILL.md` as the default.
|
||||
- Do not hand-roll request shapes. If the delegated skill has an example
|
||||
block, lift it verbatim.
|
||||
|
||||
Minimum two test files, paths taken from `plan.md` call sites:
|
||||
|
||||
- `test_mem0_write.<ext>` asserts `add()` is called at the write call site
|
||||
with the right payload shape (Platform messages-array vs OSS string) and the
|
||||
right `user_id` source.
|
||||
- `test_mem0_read.<ext>` asserts `search()` runs before the read call site and
|
||||
the result is wired into the LLM prompt or response path.
|
||||
|
||||
Tests MUST be importable with `MEM0_API_KEY` unset. This is the design
|
||||
pressure that forces step 8's lazy `MemoryClient()` / `Memory()` construction:
|
||||
eager module-level init hits the API on import and breaks pre-existing test
|
||||
collection when the key is missing.
|
||||
|
||||
Run the tests. They **must fail**. If they pass before any implementation, the
|
||||
tests are wrong. Rewrite them.
|
||||
|
||||
## 8. Implementation (subagent, fresh context)
|
||||
|
||||
Spawn a subagent with:
|
||||
|
||||
- **Inputs**: the repo, `goal.md`, `plan.md`, the two test files, and direct
|
||||
URLs to the delegated skill (from `plan.md`), the SDK source (pinned per
|
||||
`mem0_tested_versions`), `https://docs.mem0.ai/llms.txt`, and
|
||||
`https://docs.mem0.ai/openapi.json`.
|
||||
- **No access** to the main agent's reasoning trace or scratchpad.
|
||||
- **System prompt**: use the implementation prompt in
|
||||
[`subagent-prompts.md`](subagent-prompts.md) verbatim.
|
||||
|
||||
The subagent returns a diff. The main agent reviews it against `plan.md` (the
|
||||
mechanical contract) and `goal.md` (the intent):
|
||||
|
||||
- Approved, apply the diff and commit.
|
||||
- Rejected, return with specific actionable feedback, not "try again."
|
||||
- Max 3 review loops. Beyond that, exit code 4 with the last diff and the
|
||||
reviewer feedback.
|
||||
|
||||
## 9. Commit and handoff
|
||||
|
||||
Create branch `mem0-integrate/<short-goal-slug>` and commit in **separate
|
||||
commits** so reviewers can cherry-pick:
|
||||
|
||||
1. `mem0: add gated dependency`, just the `pyproject.toml` / `package.json`
|
||||
change.
|
||||
2. `mem0: add integration module`, the new files.
|
||||
3. `mem0: wire into <call site>`, the call-site edits, still gated.
|
||||
4. `mem0: add tests`, the new test files.
|
||||
|
||||
With `--no-heal`, print `Run /mem0-test-integration to verify.` and exit.
|
||||
Otherwise proceed to step 10.
|
||||
|
||||
## 10. Self-healing loop (default ON, disable with `--no-heal`)
|
||||
|
||||
Run `/mem0-test-integration --ci` in a subprocess. If `scorecard.json` reports
|
||||
`overall: pass`, done, exit 0.
|
||||
|
||||
Otherwise loop:
|
||||
|
||||
1. **Categorize the failing check** from `scorecard.json` and route:
|
||||
- `install` / `static_checks`, dependency or import fix.
|
||||
- `unit_tests`, wiring or assertion fix.
|
||||
- `smoke_test`, API key or SDK call-shape fix.
|
||||
- `e2e_test`, recipe, flag-wiring, or integration-point fix.
|
||||
- **Pre-existing test failure** (test skill exit code 7,
|
||||
`non_invasive: false` in the scorecard), **STOP**. This is a
|
||||
non-invasiveness violation. Do NOT attempt to fix it, that breaks
|
||||
principle 3. Exit code 6 with a rationale.
|
||||
|
||||
2. **Spawn a remediation subagent** with fresh context. Inputs: `plan.md`,
|
||||
`goal.md`, `scorecard.md`, `scorecard.json`, the last committed diff, and
|
||||
the relevant log for the failing category (`test-stdout.log` /
|
||||
`smoke-stdout.log` / `e2e-app.log` / `e2e-calls.log`). Use the remediation
|
||||
prompt in [`subagent-prompts.md`](subagent-prompts.md) verbatim.
|
||||
|
||||
3. **Apply the diff** and commit on the same branch as
|
||||
`mem0-heal: <category> attempt <N>`. Do NOT amend earlier commits,
|
||||
reviewers need the heal trail.
|
||||
|
||||
4. **Re-run `/mem0-test-integration --ci`**:
|
||||
- `overall: pass`, done, exit 0.
|
||||
- Same check still failing, increment the attempt counter and loop.
|
||||
- A *different* check now failing, that is a regression. Revert the heal
|
||||
commit (`git revert HEAD --no-edit`), record it in
|
||||
`.mem0-integration/heal-trace.md`, exit code 6.
|
||||
|
||||
5. **Bounded iterations.** Default 3 attempts per failing category, override
|
||||
with `--heal-max N` (hard cap 10). On exhaustion, exit code 6 with the full
|
||||
attempt trace: each diff, each scorecard, final log tail.
|
||||
|
||||
6. **Post-loop summary** written to `.mem0-integration/heal-trace.md`: which
|
||||
category failed, how many attempts, each diff's intent, final status, and
|
||||
on success the delta from the initial scorecard to the final one.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Subagent system prompts
|
||||
|
||||
Pass these verbatim. They are the only contract a fresh-context subagent gets,
|
||||
so paraphrasing them drops constraints the review step then has to catch.
|
||||
|
||||
## Step 8: implementation
|
||||
|
||||
You are implementing a Mem0 integration for an existing repo.
|
||||
|
||||
Read these first:
|
||||
- plan.md (the mechanical contract)
|
||||
- goal.md (the intent, do not change it)
|
||||
- the test files (do not change them either)
|
||||
- <delegated skill raw URL from plan.md>
|
||||
- https://docs.mem0.ai/llms.txt
|
||||
- https://docs.mem0.ai/openapi.json (Platform only)
|
||||
|
||||
Constraints, all required, all enforced at review:
|
||||
|
||||
1. Touch only the files named in plan.md's call sites, or add
|
||||
strictly new files.
|
||||
2. Do not remove or rename any existing symbol. Do not change
|
||||
any public signature.
|
||||
3. Do not modify any existing test.
|
||||
4. Gate every line of new Mem0 code behind the feature flag from
|
||||
plan.md. With the flag in its default state, the repo must
|
||||
behave exactly like `main`, byte-for-byte, including stdout
|
||||
and return values.
|
||||
5. Use only the <Platform | OSS> SDK surface. No new dependencies
|
||||
beyond those listed under plan.md's "Dependencies to add."
|
||||
6. Preserve everything listed under plan.md's "Preserved behavior"
|
||||
and "Coexistence."
|
||||
7. Lazy client construction. `MemoryClient()` validates the API
|
||||
key in `__init__` (it makes a network call). Never instantiate
|
||||
it at module-import time, construct on first use inside the
|
||||
request / handler path. The same rule applies to OSS `Memory()`,
|
||||
which can eagerly initialize embedding and LLM providers. Use
|
||||
a function-local singleton (`functools.lru_cache`, a module-level
|
||||
`_client = None` plus getter, or DI scope), never a top-level
|
||||
global. Eager init breaks the pre-existing test suite at
|
||||
collection time whenever the key is missing or invalid, which
|
||||
is a non-invasiveness violation.
|
||||
|
||||
Implement the plan to make the new tests pass while all
|
||||
pre-existing tests continue to pass unchanged.
|
||||
|
||||
Substitute `<delegated skill raw URL from plan.md>` and `<Platform | OSS>`
|
||||
before sending. Leave everything else as written.
|
||||
|
||||
## Step 10: remediation
|
||||
|
||||
You are fixing a failing Mem0 integration test.
|
||||
|
||||
Non-negotiable constraints:
|
||||
- Do not modify test files.
|
||||
- Do not remove or rename any existing symbol or signature.
|
||||
- Do not change pre-existing behavior. The feature flag from
|
||||
plan.md must still default to OFF, and with the flag in its
|
||||
default state the repo must behave exactly like main.
|
||||
- Touch only the files named in plan.md's call sites, or add
|
||||
strictly new files.
|
||||
- Return the smallest possible diff that fixes the single
|
||||
failing check listed in scorecard.md. No drive-by cleanup.
|
||||
|
||||
Never send this prompt for a pre-existing test failure. That is a
|
||||
non-invasiveness violation, and step 10 exits with code 6 instead of trying to
|
||||
heal it.
|
||||
Reference in New Issue
Block a user