Skip to content

Comments

feat: Claude Code hooks for automatic memory integration#124

Open
russellbrenner wants to merge 70 commits intoCaviraOSS:mainfrom
russellbrenner:main
Open

feat: Claude Code hooks for automatic memory integration#124
russellbrenner wants to merge 70 commits intoCaviraOSS:mainfrom
russellbrenner:main

Conversation

@russellbrenner
Copy link

Summary

Adds Claude Code integration via hooks and a migration script for users coming from claude-mem.

  • SessionStart hook - queries OpenMemory for project-relevant context at session start
  • Stop hook - stores session summaries automatically
  • CLAUDE.md.example - template instructions for Claude to use the MCP tools effectively
  • import-claude-mem.js - migration script for claude-mem SQLite databases

Both hooks fail silently with 3-second timeouts when OpenMemory isn't running.

Disclosure

This PR was authored with assistance from Claude (Anthropic). The hooks and documentation were developed iteratively based on actual usage. Happy to adjust anything to fit the project's direction.

Files

hooks/
├── openmemory-session-start.sh  # Injects context at session start
├── openmemory-session-stop.sh   # Stores session summaries
├── README.md                     # Installation instructions
└── CLAUDE.md.example            # MCP tool usage guide for Claude

scripts/
└── import-claude-mem.js         # Migrate from claude-mem

Test plan

  • Tested hooks with local OpenMemory instance
  • Verified silent failure when Docker not running
  • Tested import script with real claude-mem database

🤖 Generated with Claude Code

russellbrenner and others added 2 commits January 14, 2026 00:16
- Fix openmemory-js Dockerfile: replace Bun with npm (no bun.lockb exists)
- Add NODE_OPTIONS for increased heap size during TypeScript compilation
- Restore dashboard app from git history (removed in Beta 1.3.0)
- Update docker-compose.yml to re-enable dashboard service

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add SessionStart hook to query project context at session start
- Add Stop hook to store session summaries
- Both hooks fail silently if OpenMemory/Docker unavailable
- Include CLAUDE.md.example with comprehensive MCP tool documentation
- Add import-claude-mem.js for migrating claude-mem databases

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings January 13, 2026 14:22
Use jq to build JSON output instead of bash substring expression
that fails on some bash versions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Claude Code integration hooks and a comprehensive dashboard for OpenMemory, enabling automatic memory capture during development sessions and providing visual analytics for memory management.

Changes:

  • Added session start/stop hooks for automatic memory integration with Claude Code
  • Created a Next.js dashboard with memory analytics, chat interface, and system monitoring
  • Provided migration tooling for users coming from claude-mem
  • Switched Docker build from Bun to npm with increased Node.js heap size

Reviewed changes

Copilot reviewed 33 out of 36 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
scripts/import-claude-mem.js Migration script to import memories from claude-mem SQLite database
packages/openmemory-js/Dockerfile Changed build system from Bun to npm with heap size optimization
hooks/openmemory-session-stop.sh Bash script to capture session summaries at Claude Code session end
hooks/openmemory-session-start.sh Bash script to inject relevant context at Claude Code session start
hooks/README.md Installation and configuration guide for Claude Code hooks
hooks/CLAUDE.md.example Template documentation for Claude to use OpenMemory MCP tools
docker-compose.yml Removed obsolete version specification
dashboard/* Complete Next.js dashboard implementation with memory visualization and chat interface

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

russellbrenner and others added 2 commits January 14, 2026 12:31
- Add NODE_OPTIONS=--max-old-space-size=128 to Dockerfile production stage
- Document memory tuning in README for users needing larger heaps
- Default 128MB provides ~4x headroom over minimal Node.js heap

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous 128MB limit caused 96% memory pressure during normal
operations. Increased to 512MB to provide headroom for vector
operations and embedding storage.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@nullure
Copy link
Member

nullure commented Jan 15, 2026

Hi Russell, thank you for your contribution! This helps us a lot, but I don't understand why there is a neccesity for frontend files here

russellbrenner and others added 2 commits February 13, 2026 11:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@russellbrenner
Copy link
Author

@copilot open a new pull request to apply changes based on the comments in this thread

russellbrenner and others added 18 commits February 13, 2026 12:31
Fork cleanup: remove hardcoded CDN hostname from next.config.ts (now
env-based via NEXT_PUBLIC_CDN_HOSTNAME), add comprehensive security
scanning workflow with CodeQL, Gitleaks, and Trivy. Also includes
Dockerfile improvements and opm.js executable bit fix.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
Merge all changes from upstream repository (CaviraOSS/OpenMemory) commit 30daf78:
- Fix unterminated f-strings in google_slides.py (lines 77, 91)
- Enhanced MCP integration with temporal fact support (contextual/factual/unified queries)
- Add temporal graph user_id scoping for multi-tenant support
- Improve Postgres and Valkey vector store implementations
- Update LangChain integration with better async/await handling
- Bump versions: openmemory-py 1.3.2, openmemory-js 1.3.3
- Database improvements including better query handling
- Enhanced documentation in docstrings

Files updated: 20 (10 Python, 10 TypeScript/JavaScript)
Total changes: +404 -168 lines

Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
Fix incorrect parameter names when calling query_facts_at_time:
- Change 'obj' to 'subject_object' to match function signature
- Change 'at_time' to 'at' to match function signature

This fixes a bug introduced in the upstream code.

Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
Fix CI: Add missing pytest dev dependencies to Python SDK
Merge upstream changes from CaviraOSS/OpenMemory (30daf78)
…ent plan

- Fixed authentication bypass vulnerability with clear warnings
- Fixed error message information leakage in all routes
- Added GitHub webhook signature verification
- Updated SECURITY.md with new security features
- Added GITHUB_WEBHOOK_SECRET to .env.example
- Created comprehensive IMPROVEMENT_PLAN.md with all findings

Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
- Import crypto at module level for best practices
- Require raw body for signature verification (no fallbacks)
- Add explicit error handling if raw body unavailable
- Improve variable naming for clarity (d -> rawBody)
- Ensure byte-for-byte signature accuracy

Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
- Created SECURITY_FIXES_SUMMARY.md with detailed findings
- Documented all vulnerabilities and fixes
- Added production deployment checklist
- Confirmed 0 CodeQL alerts
- TypeScript compilation successful

Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
Co-authored-by: russellbrenner <5236354+russellbrenner@users.noreply.github.com>
…plan

Rewrite IMPROVEMENT_PLAN.md into a repo-grounded implementation roadmap with parallel execution lanes
russellbrenner and others added 2 commits February 13, 2026 22:52
Implements version history tracking for memories. Features:
- Auto-save version before content updates
- Line-based diff computation with change classification
- Version history, retrieval, comparison, and restore endpoints
- /memory/:id/versions, /version, /diff/*, /restore/:version APIs

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Copy link

@nate-mcneil nate-mcneil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is titled as Claude Code hooks but includes 96 changed files across the entire codebase -- hooks, dashboard, security hardening, auth middleware, config, CI workflows, and more. This should be broken into separate PRs. Reviewing the hooks and migration script (the stated scope) plus flagging issues in the rest.

Major concerns:

  1. PR scope: 17k+ lines across 96 files is unreviewable as a single unit. The hooks, security hardening, dashboard changes, and auth middleware are all independent concerns.

  2. Stop hook shell injection: In openmemory-session-stop.sh line 45, $project_name is interpolated directly into the JSON tags array without escaping. A directory named foo","injected would break the JSON or inject arbitrary tags. Use jq to build the entire payload.

  3. Stop hook transcript parsing is fragile: Line 29-30 pipes tail -50 of the transcript through jq with select(.type == "assistant"), but the transcript file is not necessarily newline-delimited JSON. If the format is a JSON array or changes between Claude versions, this silently produces nothing or garbage.

  4. Migration script has no idempotency: import-claude-mem.js has no deduplication. Running it twice imports everything twice. Should check for existing memories with matching original_id in metadata before inserting.

  5. Migration script has no rate limiting: It fires sequential fetch calls as fast as possible for potentially thousands of records. Should add a small delay or batch size to avoid overwhelming the server.

  6. Auth bypass on user_id checks: In memory.ts, the user_id authorization checks (lines 153, 226, 260) only enforce ownership if the caller provides a user_id. If omitted, the check is skipped entirely -- any unauthenticated caller can read/modify/delete any memory by simply not sending user_id. This is not new code but worth flagging since the PR adds auth hardening elsewhere.

\"content\": $escaped_summary,
\"user_id\": \"claude-session\",
\"tags\": [\"session\", \"project:$project_name\"]
}" > /dev/null 2>&1 || true # Ignore errors

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$project_name is interpolated raw into the JSON tags array. A directory with quotes or special characters in the name will break the JSON or inject arbitrary tags. Build the entire curl payload with jq instead of string interpolation.

# Extract recent assistant messages from transcript for summary
if [ -f "$transcript_path" ]; then
# Get last few assistant messages to summarise session
recent_content=$(tail -50 "$transcript_path" 2>/dev/null | \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes the transcript is newline-delimited JSON objects. If the transcript format is a JSON array or changes between Claude Code versions, this silently produces no summary. Worth documenting the expected format or adding a fallback.

}

try {
const response = await fetch(`${OPENMEMORY_URL}/memory/add`, {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No deduplication -- running this script twice imports everything twice. Consider checking for existing memories with matching metadata.original_id before inserting, or at minimum document that it's not idempotent.

response=$(curl -s --connect-timeout 2 --max-time "$TIMEOUT_SECS" \
-X POST "$OPENMEMORY_URL/memory/query" \
-H "Content-Type: application/json" \
-d "{\"query\": \"project $project_name\", \"k\": 5}" 2>/dev/null)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No API key / auth header is sent with the curl requests. If the user has OM_API_KEY configured (which this same PR encourages), both hooks will get 401s and silently fail. Should pass OM_API_KEY via x-api-key header when the env var is set.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 91 out of 96 changed files in this pull request and generated 14 comments.

Files not reviewed (1)
  • packages/openmemory-js/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

} {
const context = QueryAnalyzer.analyze(query)

let strategy: 'broad' | 'focused' | 'deep' | 'temporal' = 'focused'
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial value of strategy is unused, since it is always overwritten.

Copilot uses AI. Check for mistakes.
const context = QueryAnalyzer.analyze(query)

let strategy: 'broad' | 'focused' | 'deep' | 'temporal' = 'focused'
let recommendedCount = 10
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial value of recommendedCount is unused, since it is always overwritten.

Copilot uses AI. Check for mistakes.
const [messages, setMessages] = useState<ChatMessage[]>([])
const [input, setInput] = useState("")
const [busy, setBusy] = useState(false)
const [connecting, setConnecting] = useState(false)
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable setConnecting.

Suggested change
const [connecting, setConnecting] = useState(false)
const [connecting] = useState(false)

Copilot uses AI. Check for mistakes.
const [riskmems, setriskmems] = useState<memory[]>([])
const [loading, setloading] = useState(true)
const [error, seterror] = useState<string | null>(null)
const [dashstats, setdashstats] = useState<any>(null)
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable dashstats.

Suggested change
const [dashstats, setdashstats] = useState<any>(null)

Copilot uses AI. Check for mistakes.
const [qpsData, setQpsData] = useState<any[]>([])
const [healthMetrics, setHealthMetrics] = useState<any>({})
const [logs, setLogs] = useState<any[]>([])
const [topUsers, setTopUsers] = useState<any[]>([])
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable topUsers.

Suggested change
const [topUsers, setTopUsers] = useState<any[]>([])

Copilot uses AI. Check for mistakes.

if (contextSegments.length > 0) {
for (const seg of contextSegments) {
const sources = seg.sources.map(id => `[${id.slice(0, 8)}]`).join(' ')
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable sources.

Copilot uses AI. Check for mistakes.
const idealPercentage = 1 / sectors.length

let balance = 0
for (const [sector, count] of sectors) {
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable sector.

Copilot uses AI. Check for mistakes.
const connectivity = node ? node.linkedMemories.length / Math.max(1, allMemories.length) : 0

const tokens = TextProcessor.tokenize(memory.content)
const allTokens = new Set(allMemories.flatMap(m => TextProcessor.tokenize(m.content)))
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable allTokens.

Copilot uses AI. Check for mistakes.
// Set up environment before importing audit module
process.env.OM_EMBEDDINGS = "synthetic";

import { run_async, all_async, get_async } from "../src/core/db";
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports all_async, get_async.

Copilot uses AI. Check for mistakes.
// Set up environment before importing
process.env.OM_EMBEDDINGS = "synthetic";

import { run_async, all_async, q } from "../src/core/db";
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports all_async, q.

Copilot uses AI. Check for mistakes.
russellbrenner and others added 24 commits February 14, 2026 10:08
Word-level diff with automatic categorisation of changes into financial,
date, party, legal_term, and general categories. Severity calculation based
on change type and volume. Generates HTML redline markup with data attributes.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Extracts citations from text using pattern matching for legal (case law,
legislation), academic (author-date, footnotes), and URL references.
Stores citations with edges to source memories for reverse-lookup.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Schema-driven extraction for document types: agreement, contract, invoice,
legal_filing, correspondence. Validates with zod, supports merge with
existing metadata. Extracts parties, dates, amounts, jurisdiction, etc.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Segments documents into clauses with type detection (definition, obligation,
confidentiality, termination, etc.). Stores clause embeddings for similarity
search across documents. Detects various numbering formats.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
CRUD for document templates with typed variables (string, number, date,
boolean, select, list). Auto-extracts variables from {{var:type}} syntax.
Instantiation validates and substitutes variables, creating memory entries.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
C2: Add scripts/check-sector-parity.ts to verify TS/Python config sync
D7: Implement compliance rules engine with 7 rule types:
- required_clause: Ensure specific clauses are present
- prohibited_term: Flag forbidden terms with context
- required_field: Validate metadata field presence
- pattern_match: Custom regex matching (must/must-not)
- field_format: Validate field format with regex
- word_count: Enforce min/max word limits
- date_range: Validate dates within bounds

Includes rule sets for grouping rules, full CRUD API, and audit logging.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Created project-level CLAUDE.md for future Claude Code sessions with
build commands, architecture overview, and sector/scoring documentation.
Added comprehensive 48-hour code review identifying 2 critical bugs
and 5 improvement opportunities across new document intelligence features.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Critical fixes:
- Fix operator precedence bug in structured_extraction.ts:269
- Fix prohibited_term to report all matches in compliance.ts

High priority:
- Batch embedding calls in clause_similarity store_clauses()
- Add ReDoS protection for user-provided regex patterns

Medium priority:
- Standardise UUID generation on rid() across codebase
- Add version pruning to prevent unbounded growth

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Replace hardcoded 'memories' table references with the dynamic
memories_table variable to support PostgreSQL deployments where
the table is named "public"."openmemory_memories".

Fixed files:
- src/ops/dynamics.ts: 3 queries for salience retrieval and decay
- src/memory/decay.ts: 1 SELECT, 2 UPDATE queries for summary updates
- src/server/routes/system.ts: 1 SELECT for sector statistics

Discovered during integration testing against the test k3s deployment.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AI-Generated: true
- audit.ts: Extend resource_type to include compliance_rule, rule_set, template
- clause_similarity.ts: Fix VectorStore method names (storeVector, searchSimilar)
- structured_extraction.ts: Fix TypeScript doc_type spread conflict
- embed.ts: Add embed_advanced() batch function for clause embeddings
- audit routes: Accept new resource types in validation
- templates.ts: Fix add_memory signature to match add_hsg_memory

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Add comprehensive analysis of Redis/Valkey caching layer requirements.
Conclusion: not needed at current scale, but architecture is ready.

Also add gitignore pattern for auto-generated claude-mem context files
in subdirectories while preserving root CLAUDE.md.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
- Add Voyage AI as embedding provider (voyage-3 recommended, 7.55% better than OpenAI)
- Add emb_voyage() and emb_batch_voyage() functions with OpenAI-compatible API
- Add Voyage model defaults per sector (voyage-3-large for reflective)
- Add vector storage metrics: vectors_total, vector_dimensions, vector_index_size_bytes
- Instrument embed.ts with record_embedding() calls for latency tracking
- Update /metrics endpoint with pgvector index stats and embed_logs counts
- Document Voyage configuration in README.md and CLAUDE.md
- Scaffold Legal RAG MCP tool concept in Scratch/

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Script to bulk re-embed all memories with current provider (Voyage).
Usage: npx tsx scripts/reembed-all.ts [--dry-run] [--batch-size=50]

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
- Add prom-client for Prometheus metrics exposition
- Add /metrics endpoint with HTTP request, background task, and memory metrics
- Add embedding cost tracking with token usage and USD cost counters
- Track costs per provider/model with configurable pricing table
- Add request duration middleware for HTTP latency metrics
- Integrate background task metrics with observability module

Metrics exposed:
- openmemory_http_requests_total (method, path, status_code)
- openmemory_http_request_duration_seconds (method, path)
- openmemory_embedding_tokens_total (provider, model)
- openmemory_embedding_cost_dollars_total (provider, model)
- openmemory_background_task_runs_total (task_name, status)
- openmemory_info (version, tier, embedding_provider, backends)
- Node.js default metrics (heap, GC, event loop)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AI-Generated: true
Timestamps stored as strings were rendering as Invalid Date in the
memories list. Explicit Number() cast fixes the display.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
- Hoist all regex patterns in compress.py to module-level compiled constants
  (17 standalone patterns + 4 pattern lists = ~40 patterns total)
- Add auth middleware with hmac.compare_digest for timing-safe API key
  comparison, matching the TypeScript server/middleware/auth.ts parity
- Add api_key/require_auth/port fields to EnvConfig
- Wire AuthMiddleware into FastAPI app via server/api.py

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
…gestion, payload validation

- OM-1: surface deduplicated/upserted flags in openmemory_store MCP response text
- OM-2: add upsert_key named upsert to db/hsg/mcp/memory stack
- OM-3: add section_strategy=by_section to ingest pipeline with frontmatter parsing
- OM-4: add OM_MAX_INGEST_BYTES pre-decode size guard in ingest route

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
- OM-5: fetch actual sector list on dedup return path in hsg.ts
- OM-6: canonical content_type normalisation map in extract.ts
- OM-7: structured timing log per MCP tool (tool, dur, in/out bytes)
- OM-8: MIME whitelist validation with helpful error message

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
…OM-12)

OM-9: dedup_count/dedup_last_at columns (SQLite+PG), migration guards,
      counter increment on dedup path, exposed in openmemory_get response
OM-10: memory_dedup_total counter and memory_dedup_hamming histogram in
       metrics.ts, instrumented in hsg.ts dedup path
OM-11: metadata_only parameter on openmemory_query strips content from
       both contextual and factual results for lightweight lookups
OM-12: openmemory_stats MCP tool with sector distribution, dedup stats,
       7-day growth, orphan count; 4 new Prometheus gauges for operational
       monitoring; Grafana dashboard JSON

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
… (OM-13..OM-15)

OM-13: Automated maintenance scheduler running on decay interval:
       prune embed_logs older than OM_EMBED_LOG_RETENTION_DAYS (default 30),
       expire dead memories (low salience + no waypoints + old + not pinned),
       update orphan/growth Prometheus gauges, SQLite VACUUM.
       New cfg vars: embed_log_retention_days, dead_memory_min_salience,
       dead_memory_max_age_days.

OM-14: Replace .catch(console.error) in memory.ts fire-and-forget ops
       with contextual bg_err() handler that logs op name, memory ID,
       and increments background_task_runs_total failure counter.

OM-15: decay_disabled metadata flag in decay.ts skips salience decay
       for pinned memories (e.g. legal documents). Dead memory expiry
       in maintenance scheduler also excludes decay_disabled memories.
       Documented in openmemory_store MCP tool description.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
- OM-2: fix upsert_key lookup — query was filtering by user_id but ins_mem
  stores 'anonymous' as fallback; simplified to key-only lookup since
  upsert_key is a global stable identifier (users should namespace if needed)
- OM-9/OM-11: expose dedup_count, dedup_last_at, upsert_key in HTTP GET
  /memory/:id response (was MCP-only); add metadata_only param to HTTP
  POST /memory/query (was MCP-only, HTTP route not updated)
- All 5 e2e verification tests now pass locally

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
…hboard

Builds both images on push to main and pushes to git.itsa.house/homelab/
with latest and SHA tags. Uses buildah with chroot isolation for ZFS-compatible
LXC builds.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Add sanitise_content() called at the top of add_hsg_memory() to strip
{"type": "thinking"}, {"type": "tool_use"}, and {"type": "tool_result"}
JSON blocks before they reach the DB. Memories that reduce to fewer than
20 chars after sanitisation are rejected with a clear error.

Prevents Claude's internal extended thinking monologue from accumulating
as noise in the memory store when /remember or similar skills are run.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
The < 20 char length check fired on legitimately short memories
(e.g. "Finish Report" = 13 chars), failing the omnibus Phase 2 test.

Changed to only reject content that was non-empty before sanitisation
but is empty/whitespace after — i.e. the sanitiser consumed all content.
Omnibus: all 3 phases pass.

Co-Authored-By: Claude <noreply@anthropic.com>
AI-Generated: true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants