Skip to content

Releases: pitimon/c-memforge

v2.4.3 — Fix sync response field path (#55)

14 Apr 06:13

Choose a tag to compare

Bug Fix

SyncPoller false failuresremote-sync.ts read result.observations but server returns data under result.tables.observations. Every successful push was misclassified as failure, causing:

  • Watermark never advancing (stuck at 74,792)
  • Phantom failure count growing on every poll
  • Redundant re-uploads of already-synced observations

Changes

  • Fix field path in syncBatch() and syncSummaries() to use result.tables.*
  • Add 7 contract tests pinned to real server response shape

Upgrade

claude mcp update pitimon-c-memforge

Closes #55 | Sequel to #51

v2.3.1 — Fix silent data loss in SyncPoller

02 Apr 23:20
aa94a3c

Choose a tag to compare

CRITICAL FIX: Silent data loss prevented

2,580 observations were permanently lost on a production client due to a JavaScript 0 || N falsy bug that reported zero syncs as full-batch success, advancing the watermark past unsynced data.

Fixes

  1. 0 || N falsy bug (CRITICAL) — syncBatch() now treats zero-sync on non-empty batch as failure
  2. Unbounded batch queries (HIGH) — Added LIMIT 100 + batch loop to prevent OOM and timeout
  3. All-or-nothing watermark (HIGH) — Watermark now advances only past successfully synced items

Update

claude plugin update memforge-client@pitimon-c-memforge

After update — verify sync works

# Reset watermark to re-sync
rm -f ~/.memforge/.sync-watermark.json

# Restart Claude Code — should see batched sync in logs:
# [SyncPoller] Fresh install — backfilling N existing observations

Closes #51

v2.3.0 — Watermark Persistence Fix

02 Apr 07:50
4590fb8

Choose a tag to compare

Fix: SyncPoller watermark now persisted to disk

Observations created before c-memforge install were permanently skipped because the watermark reset to MAX(id) on every start. This release fixes the root cause.

Changes

  • Watermark saved to ~/.memforge/.sync-watermark.json after each successful sync
  • Restored from disk on restart (no more data loss during downtime)
  • backfillFrom(id) method for manual recovery of pre-install observations

For existing users with missing observations

# Option A: Delete watermark to re-sync from MAX(id)
rm ~/.memforge/.sync-watermark.json

# Option B: Edit watermark to sync everything from the beginning
echo '{"lastObservationId":0,"lastSummaryId":0}' > ~/.memforge/.sync-watermark.json

Then restart Claude Code.

Update

claude plugin update pitimon-c-memforge

Closes #48

v2.1.1 — Testing & Observability

19 Mar 21:15
26bec1c

Choose a tag to compare

Improvements

Unit Tests (+20, total 86)

  • PendingQueue: 8 tests — add, dedup, retry, clearFailed, edge cases
  • SyncPoller: 12 tests — construction, stats shape, lifecycle, start/stop

Structured Logging

Log messages now include ISO timestamps and levels:

[2026-03-20T01:23:45.678Z] [INFO] [SyncPoller] Starting (interval=2000ms)
[2026-03-20T01:23:45.678Z] [ERROR] [SyncPoller] Circuit OPEN — remote unreachable

Schema Validation

SyncPoller verifies observations, session_summaries, sdk_sessions tables exist before polling. Prevents cryptic SQL errors if claude-mem DB schema changes.

8-Habit Score: 38.5/40 → ~40/40

All 3 remaining gaps from QA assessment (#34) addressed.

Full diff: #35

v2.1.0 — SyncPoller Improvements

19 Mar 14:07

Choose a tag to compare

New Features

1. Sync stats in mem_status

mem_status tool now shows sync health: synced count, failed count, pending queue size, and circuit state.

2. Adaptive polling

Polling interval adjusts automatically:

  • Active (new data found): polls every 1s for faster sync
  • Idle (no new data): ramps from 2s → 4s → 8s → 10s (capped)
  • Result: ~80% fewer empty database polls during idle periods

3. Circuit breaker

When the remote server is unreachable:

  • After 3 consecutive failures: circuit opens, skips HTTP calls for 30s
  • After cooldown: sends one probe request (half-open state)
  • On success: circuit closes, normal polling resumes
  • Result: ~93% fewer failed requests during outages

4. Pending queue cleanup

Items exceeding max retries (5) are now removed from the in-memory queue after each retry cycle, preventing slow memory leak during long sessions.

Technical Changes

  • setIntervalsetTimeout chain for adaptive timing
  • checkNewObservations/checkNewSummaries now return row count
  • SyncStats interface extended with pendingCount, circuitState, currentInterval
  • syncPoller exported from mcp-server.ts for status handler access

Closes #32

Full diff: #33

v2.0.1 — Fix snapshot endpoints

19 Mar 13:24

Choose a tag to compare

Bug Fix

  • Add /api/snapshots to ALLOWED_API_PATHS SSRF allowlist
  • Fixes all 4 snapshot tools (mem_snapshot_create/list/restore/delete) throwing Unknown endpoint: /api/snapshots

Closes #25

v2.0.0 — Simplify Sync

19 Mar 13:14
efe6344

Choose a tag to compare

Breaking Changes

  • Sync moved into MCP server process — the detached db-watcher daemon is removed. Sync now starts automatically when the MCP server starts (if syncEnabled: true in config).
  • bun run sync and bun run sync-manager scripts removed.
  • SessionStart hook no longer needed — removed from .claude-plugin/hooks/hooks.json.

What Changed

Before (v1.3.x) After (v2.0.0)
Sync process Detached daemon via SessionStart hook In-process poller inside MCP server
State files 5 (config, watermark, queue, PID, log) 1 (config.json only)
Orphaned processes Daemon persists after session ends None
Code db-watcher.ts (345 LOC) + sync-manager.ts (289 LOC) sync-poller.ts (~230 LOC)

Migration

Run bun run setup "your-api-key" to automatically:

  1. Kill any running legacy daemon
  2. Delete legacy state files (watermark, queue, PID, log)
  3. Remove SessionStart hook from ~/.claude/settings.json

Your existing ~/.memforge/config.json is preserved.

Closes

  • #23 — Simplify sync: reduce local state files

Full diff: #24

v1.2.3

10 Mar 13:58

Choose a tag to compare

Fixes

  • Fix ${CLAUDE_PLUGIN_ROOT} not expanded in args (#17) — moved path to command field where Claude Code actually expands it; mcp-server.ts shebang handles bun runtime
  • Fix ESM re-export bugexport { X } from doesn't create local bindings; switched to explicit import + export
  • Version syncplugin.json was stuck at 1.1.0, now aligned with package.json

Full Changelog

v1.2.2...v1.2.3

v1.2.2 — Security hardening + ESM fix

10 Mar 13:35

Choose a tag to compare

Critical Fix

  • ESM re-export bug — MCP server failed to start because export { X } from doesn't create local bindings for getAllTools(). Fixed with import + explicit export.

Security Fixes

  • MEMFORGE_ALLOW_CUSTOM_URL=1 now still enforces HTTPS + blocks cloud metadata IPs (Closes #15)
  • Block 0.0.0.0 and [::] in SSRF private host detection
  • Entity handlers routed through callRemoteAPI() (SSRF + timeout protection)
  • AbortError (timeout) never retried — prevents 90s hangs

Quality Improvements

  • Version synced from package.json (was hardcoded 1.0.0)
  • Retry logic with exponential backoff for transient TLS/network errors
  • Fixed tsconfig.json rootDir mismatch

Tests

  • 66 tests, 100 expect() calls (up from 37 in v1.2.1)

Upgrade

cd ~/.claude/plugins/cache/pitimon-c-memforge/memforge-client/*/
git pull && bun install

Full Changelog: v1.2.1...v1.2.2

v1.2.1 — Security hardening

10 Mar 12:45
63e5d53

Choose a tag to compare

Security Fixes

Addresses all 7 findings from static analysis (#13):

# Severity Fix
1 MEDIUM SSRF protection — URL allowlist with private IP blocking
2 MEDIUM Zod runtime validation for all 12 MCP tool inputs
3 MEDIUM Strict endpoint allowlist with path traversal normalization
4 LOW Restricted env vars passed to child watcher process
5 LOW Removed API key character exposure from mem_status
6 LOW Enforced batch cap (100) and required fields for mem_ingest
7 LOW Structured audit logging for all tool invocations

New Files

  • src/mcp/validation.ts — Zod schemas for all MCP tools
  • src/mcp/audit-logger.ts — Structured JSON audit logging to stderr

Testing

  • 37 new unit tests added
  • Self-hosted deployments: set MEMFORGE_ALLOW_CUSTOM_URL=1 to bypass URL allowlist

Upgrade

claude-code plugin update memforge-client
# or
cd ~/.claude/plugins/memforge-client && git pull && bun install

Full Changelog: v1.1.1...v1.2.1