From 56b897cdccea09835dec5f30f32d21871acc40d1 Mon Sep 17 00:00:00 2001 From: Jack Arturo Date: Sat, 29 Aug 2026 02:26:27 +0200 Subject: [PATCH 1/2] docs(cli): reconcile queue behavior --- src/content/docs/docs/cli/queue.md | 33 +++++++++++-------- tests/queue-docs.test.mjs | 51 ++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 tests/queue-docs.test.mjs diff --git a/src/content/docs/docs/cli/queue.md b/src/content/docs/docs/cli/queue.md index 8621cbae..a59c5130 100644 --- a/src/content/docs/docs/cli/queue.md +++ b/src/content/docs/docs/cli/queue.md @@ -46,7 +46,7 @@ graph TB ### UpdateMemoryArgs Parameters -The `update_memory` tool accepts the following parameters (defined in [`src/types.ts`](https://github.com/verygoodplugins/mcp-automem/blob/538721c/src/types.ts)): +The `update_memory` tool accepts the following parameters (defined in [`src/types.ts`](https://github.com/verygoodplugins/mcp-automem/blob/9a0bbf754dd31db524da25638b0e97907e32ff37/src/types.ts)): | Parameter | Type | Required | Description | |---|---|---|---| @@ -56,6 +56,8 @@ The `update_memory` tool accepts the following parameters (defined in [`src/type | `importance` | `number` (0-1) | No | New importance score | | `metadata` | `object` | No | New metadata (replaces existing entirely) | | `timestamp` | `string` (ISO) | No | Override creation timestamp | +| `t_valid` | `string` (ISO) | No | Time when the memory becomes valid | +| `t_invalid` | `string` (ISO) | No | Time when the memory expires or becomes invalid | | `updated_at` | `string` (ISO) | No | Explicit update timestamp | | `last_accessed` | `string` (ISO) | No | Last access timestamp | | `type` | `string` | No | Memory type classification | @@ -136,7 +138,7 @@ graph TB ### DeleteMemoryArgs Parameters -The `delete_memory` tool accepts the following parameters (defined in [`src/types.ts`](https://github.com/verygoodplugins/mcp-automem/blob/538721c/src/types.ts)). Use either `memory_id` or `tags` — they are mutually exclusive deletion modes: +The `delete_memory` tool accepts the following parameters (defined in [`src/types.ts`](https://github.com/verygoodplugins/mcp-automem/blob/9a0bbf754dd31db524da25638b0e97907e32ff37/src/types.ts)). Use either `memory_id` or `tags` — they are mutually exclusive deletion modes: | Parameter | Type | Required | Description | |---|---|---|---| @@ -211,17 +213,22 @@ graph TB ### HealthStatus Response Structure -The `check_database_health` tool returns a `HealthStatus` object (defined in [`src/types.ts`](https://github.com/verygoodplugins/mcp-automem/blob/538721c/src/types.ts)): +The `check_database_health` tool returns a `HealthStatus` object (defined in [`src/types.ts`](https://github.com/verygoodplugins/mcp-automem/blob/9a0bbf754dd31db524da25638b0e97907e32ff37/src/types.ts)): | Field | Type | Description | |---|---|---| | `status` | `"healthy"` \| `"degraded"` \| `"error"` | Overall health status (`degraded` means the service is reachable but a backend or sync check needs attention) | | `backend` | `string` | Backend type (always `"automem"`) | -| `statistics` | `object` | Database statistics and connection info | -| `statistics.falkordb` | `string` | FalkorDB connection status | -| `statistics.qdrant` | `string` | Qdrant connection status | -| `statistics.graph` | `string` | Graph database name | -| `statistics.timestamp` | `string` | Health check timestamp | +| `statistics` | `object` | Optional database statistics and diagnostics | +| `statistics.falkordb` | `any` (optional) | FalkorDB statistics or diagnostics when supplied by the service | +| `statistics.qdrant` | `any` (optional) | Qdrant statistics or diagnostics when supplied by the service | +| `statistics.graph` | `string` (optional) | Graph database name | +| `statistics.timestamp` | `string` (optional) | Health check timestamp | +| `statistics.memory_count` | `number` (optional) | Number of stored memories | +| `statistics.vector_count` | `number` (optional) | Number of stored vectors | +| `statistics.sync_status` | `string` (optional) | Vector synchronization status | +| `statistics.vector_dimensions` | `Record` (optional) | Vector dimension diagnostics | +| `statistics.enrichment` | `Record` (optional) | Enrichment diagnostics | | `error` | `string` (optional) | Error message if status is `"error"` | ### Health Check Use Cases @@ -306,7 +313,7 @@ The `queue` CLI command processes pending memories from a local JSONL queue file npx @verygoodplugins/mcp-automem queue # Process a specific queue file (JSONL — one entry per line) -npx @verygoodplugins/mcp-automem queue --file /path/to/memory-queue.jsonll +npx @verygoodplugins/mcp-automem queue --file /path/to/memory-queue.jsonl # Preview what would be processed without writing npx @verygoodplugins/mcp-automem queue --dry-run @@ -326,7 +333,7 @@ graph TB ConfigResolve["Config resolution
AUTOMEM_API_URL → ~/.claude.json → default"] HealthCheck["Health check
GET /health"] QueueEntries["Read pending entries
local queue file"] - ProcessEntry["Process each entry
POST /memory or PATCH /memory/{id}"] + ProcessEntry["Process each entry
storeMemory(), then optional associateMemories()"] Cleanup["Remove processed entries
from queue file"] end @@ -350,13 +357,11 @@ graph TB ### Service Unavailability Handling -The queue command skips processing if the endpoint is unreachable — this prevents queue operations from blocking when the service is down. The queue entries are preserved for the next run. +The queue command reads records from a local `.jsonl` file, then calls `storeMemory()` for each valid record. When a queued record includes `relatesTo`, the command optionally follows the successful store with `associateMemories()`. It does not update queued records through a queue-specific PATCH path. If the endpoint is unreachable, it skips processing and preserves the entries for the next run. ``` $ npx @verygoodplugins/mcp-automem queue -Checking AutoMem service at http://localhost:8001... -❌ Service unavailable - skipping queue processing -Queue will be retried on next run +AutoMem endpoint unavailable; skipping queue drain. ``` ### Error Handling Patterns diff --git a/tests/queue-docs.test.mjs b/tests/queue-docs.test.mjs new file mode 100644 index 00000000..5632edbc --- /dev/null +++ b/tests/queue-docs.test.mjs @@ -0,0 +1,51 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { readFile } from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; + +const defaultPagePath = fileURLToPath( + new URL('../src/content/docs/docs/cli/queue.md', import.meta.url), +); +const pagePath = process.env.QUEUE_DOCS_PAGE_PATH || defaultPagePath; +const releaseSha = '9a0bbf754dd31db524da25638b0e97907e32ff37'; + +async function readPage() { + return readFile(pagePath, 'utf8'); +} + +test('queue docs match the audited mcp-automem 0.16.0 queue and type surfaces', async () => { + const page = await readPage(); + + assert.match(page, new RegExp(releaseSha, 'u')); + assert.doesNotMatch(page, /538721c/u); + assert.match(page, /memory-queue\.jsonl/u); + assert.doesNotMatch(page, /\.jsonll/u); + + const queueSection = page.split('## Queue Processing CLI Command')[1]; + assert.ok(queueSection, 'queue section is present'); + assert.match(queueSection, /storeMemory[\s\S]*associateMemories/i); + assert.doesNotMatch(queueSection, /POST \/memory or PATCH \/memory\/\{id\}/u); + assert.doesNotMatch(queueSection, /PATCH \/memory\/\{id\}/u); + assert.match(queueSection, /AutoMem endpoint unavailable; skipping queue drain\./u); + assert.doesNotMatch(queueSection, /Service unavailable - skipping queue processing/u); + assert.doesNotMatch(queueSection, /Queue will be retried on next run/u); + + for (const field of [ + 'falkordb', + 'qdrant', + 'graph', + 'timestamp', + 'memory_count', + 'vector_count', + 'sync_status', + 'vector_dimensions', + 'enrichment', + ]) { + assert.match(page, new RegExp('statistics\\.' + field, 'u')); + } + assert.match(page, /`statistics\.falkordb`[\s\S]*`any`/u); + assert.match(page, /`statistics\.qdrant`[\s\S]*`any`/u); + + assert.match(page, /\| `t_valid` \| `string` \(ISO\) \| No \|/u); + assert.match(page, /\| `t_invalid` \| `string` \(ISO\) \| No \|/u); +}); From f11a06cdfe059d4282aa7f4c79ab99d4c67e4cf5 Mon Sep 17 00:00:00 2001 From: Jack Arturo Date: Sat, 29 Aug 2026 02:28:06 +0200 Subject: [PATCH 2/2] test(docs): tighten queue reconciliation guard --- tests/queue-docs.test.mjs | 40 +++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/tests/queue-docs.test.mjs b/tests/queue-docs.test.mjs index 5632edbc..15c55fa9 100644 --- a/tests/queue-docs.test.mjs +++ b/tests/queue-docs.test.mjs @@ -18,33 +18,45 @@ test('queue docs match the audited mcp-automem 0.16.0 queue and type surfaces', assert.match(page, new RegExp(releaseSha, 'u')); assert.doesNotMatch(page, /538721c/u); + const typeSourceLinks = [ + ...page.matchAll(/\[[^\]]*src\/types\.ts[^\]]*\]\(([^)]+)\)/gu), + ].map((match) => match[1]); + assert.deepEqual(typeSourceLinks, [ + `https://github.com/verygoodplugins/mcp-automem/blob/${releaseSha}/src/types.ts`, + `https://github.com/verygoodplugins/mcp-automem/blob/${releaseSha}/src/types.ts`, + `https://github.com/verygoodplugins/mcp-automem/blob/${releaseSha}/src/types.ts`, + ]); assert.match(page, /memory-queue\.jsonl/u); assert.doesNotMatch(page, /\.jsonll/u); const queueSection = page.split('## Queue Processing CLI Command')[1]; assert.ok(queueSection, 'queue section is present'); - assert.match(queueSection, /storeMemory[\s\S]*associateMemories/i); + assert.match( + queueSection, + /calls `storeMemory\(\)` for each valid record\. When a queued record includes `relatesTo`, the command optionally follows the successful store with `associateMemories\(\)`\./u, + ); assert.doesNotMatch(queueSection, /POST \/memory or PATCH \/memory\/\{id\}/u); assert.doesNotMatch(queueSection, /PATCH \/memory\/\{id\}/u); assert.match(queueSection, /AutoMem endpoint unavailable; skipping queue drain\./u); assert.doesNotMatch(queueSection, /Service unavailable - skipping queue processing/u); assert.doesNotMatch(queueSection, /Queue will be retried on next run/u); - for (const field of [ - 'falkordb', - 'qdrant', - 'graph', - 'timestamp', - 'memory_count', - 'vector_count', - 'sync_status', - 'vector_dimensions', - 'enrichment', + for (const [field, type] of [ + ['falkordb', 'any'], + ['qdrant', 'any'], + ['graph', 'string'], + ['timestamp', 'string'], + ['memory_count', 'number'], + ['vector_count', 'number'], + ['sync_status', 'string'], + ['vector_dimensions', 'Record'], + ['enrichment', 'Record'], ]) { - assert.match(page, new RegExp('statistics\\.' + field, 'u')); + assert.ok( + page.includes(`| \`statistics.${field}\` | \`${type}\` (optional) |`), + `statistics.${field} has exact ${type} optional table row`, + ); } - assert.match(page, /`statistics\.falkordb`[\s\S]*`any`/u); - assert.match(page, /`statistics\.qdrant`[\s\S]*`any`/u); assert.match(page, /\| `t_valid` \| `string` \(ISO\) \| No \|/u); assert.match(page, /\| `t_invalid` \| `string` \(ISO\) \| No \|/u);