Community-testing guide for the new memory-conflict-surfacing features. Runs in complete isolation from your existing engram setup.
| Phase | What it adds |
|---|---|
| 2 — Cloud sync of relations | memory_relations (conflict verdicts) now sync across machines. Multi-actor scenarios persist correctly. Server validates relation payloads. |
| 3 — Admin observability | New engram conflicts list/show/stats/scan/deferred CLI + 6 HTTP endpoints under /conflicts/* for retroactive audit + scan over existing memories using FTS5. |
| 4 — Semantic LLM-judge | New --semantic scan flag uses your existing Claude Code or OpenCode CLI to catch vocabulary-different conflicts (e.g. "Hexagonal" ↔ "Ports and Adapters") that FTS5 alone misses. $0 if you're on a subscription (Pro/Max/Plus). |
Everything below uses non-default ports, a separate data dir, a separate token, and the binary is built locally as ./engram-beta. Your production engram cloud, your ~/.engram/engram.db, and your installed engram binary are NOT touched.
Reset anytime with the cleanup section at the end.
- Docker + Docker Compose
- Go 1.26+ (to build the beta binary — see
go.mod) - For Phase 4 testing:
claudeoropencodeCLI installed and authenticated (whichever you already use) - On Windows: PowerShell 7+ for the PowerShell commands below
git clone https://github.com/Gentleman-Programming/engram.git engram-beta-repo
cd engram-beta-repo
git checkout feat/memory-conflict-surfacing-cloud-syncWindows PowerShell 7: Run this in the dedicated beta-only PowerShell session used for the remaining Windows steps.
git clone https://github.com/Gentleman-Programming/engram.git engram-beta-repo
Set-Location engram-beta-repo
git checkout feat/memory-conflict-surfacing-cloud-syncdocker compose -f docker-compose.beta.yml up -dWhat this starts (all bound to 127.0.0.1 only):
engram-beta-postgreson port 25432 (your prod's 5433 untouched)engram-beta-cloudon port 28080 (your prod's 18080 untouched)- Volume
engram-beta-pg(separate from prod data)
Verify it's up:
curl -s http://127.0.0.1:28080/health
# Expected: {"status":"ok",...}Windows PowerShell 7:
$health = Invoke-RestMethod -Uri http://127.0.0.1:28080/health
$health
# Expected: status is okgo build -o ./engram-beta ./cmd/engramWindows PowerShell 7:
$betaClonePath = (Get-Location).Path
$betaBinaryPath = Join-Path $betaClonePath 'engram-beta.exe'
$betaBinaryOwnedByThisRun = $false
if (Test-Path -LiteralPath $betaBinaryPath -PathType Leaf) {
throw "Refusing to overwrite an existing beta binary: $betaBinaryPath"
}
go build -o $betaBinaryPath .\cmd\engram
if ($LASTEXITCODE -ne 0) {
throw "Failed to build the beta binary."
}
$betaBinaryOwnedByThisRun = $trueA standalone ./engram-beta in your repo dir. Does NOT replace your installed engram.
On Windows, the standalone binary is .\engram-beta.exe and likewise does not replace your installed engram.
Run these in the same shell where you'll execute the beta commands:
# Separate data dir — leaves ~/.engram untouched
export ENGRAM_DATA_DIR=/tmp/engram-beta-data
mkdir -p "$ENGRAM_DATA_DIR"
# Point at the beta cloud
export ENGRAM_CLOUD_SERVER=http://127.0.0.1:28080
export ENGRAM_CLOUD_TOKEN=beta-token-CHANGE-ME-please-32chars
# Verify
./engram-beta version
./engram-beta cloud statusExpected: cloud status shows configured=true, server matches the beta URL.
Windows PowerShell 7: Continue in the same dedicated beta-only PowerShell session. Close it after cleanup so its session-scoped ENGRAM_* values cannot affect later normal Engram commands.
# Create a unique, run-owned data root
$betaRunRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("engram-beta-" + [guid]::NewGuid().ToString('N'))
$betaDataDir = Join-Path $betaRunRoot 'data'
New-Item -ItemType Directory -Path $betaRunRoot -ErrorAction Stop | Out-Null
New-Item -ItemType Directory -Path $betaDataDir -ErrorAction Stop | Out-Null
$env:ENGRAM_DATA_DIR = $betaDataDir
Write-Host "Beta run root (copy this into a second beta window if needed): $betaRunRoot"
# Point at the beta cloud for this PowerShell session only
$env:ENGRAM_CLOUD_SERVER = 'http://127.0.0.1:28080'
$env:ENGRAM_CLOUD_TOKEN = 'beta-token-CHANGE-ME-please-32chars'
# Verify
& $betaBinaryPath version
& $betaBinaryPath cloud statusFor the remaining workflow snippets, stay in this dedicated beta session and use & $betaBinaryPath wherever the POSIX version shows ./engram-beta. Keep commands on one line, or replace Bash's trailing \ continuation with PowerShell's trailing backtick. The POSIX snippets remain unchanged for POSIX shells.
The CLI save syntax is positional: engram save <title> <content> [flags].
# First memory
./engram-beta save \
"Use Clean Architecture" \
"Layers: entities, use cases, adapters." \
--type architecture --project beta-test
# Conflicting memory
./engram-beta save \
"Use Hexagonal Architecture" \
"Ports and adapters separate domain from infra." \
--type architecture --project beta-testThe second save should return candidates[] with the first memory's id and a judgment_id. This is Phase 1 behavior — base feature already shipped, included here as sanity check.
# Enroll the project for cloud sync
./engram-beta cloud enroll beta-test
# Sync to beta cloud
./engram-beta sync --cloud --project beta-test
# Check status
./engram-beta cloud statusExpected: phase: healthy, sync mutations pushed to the beta cloud.
To verify cross-machine: create a 2nd data dir and pull:
# Simulate a "second machine"
export ENGRAM_DATA_DIR_2=/tmp/engram-beta-data-2
mkdir -p "$ENGRAM_DATA_DIR_2"
ENGRAM_DATA_DIR="$ENGRAM_DATA_DIR_2" ./engram-beta cloud enroll beta-test
ENGRAM_DATA_DIR="$ENGRAM_DATA_DIR_2" ./engram-beta sync --cloud --project beta-test
ENGRAM_DATA_DIR="$ENGRAM_DATA_DIR_2" ./engram-beta search "Architecture" --project beta-testThe 2nd "machine" should see the memories synced from the 1st.
Windows PowerShell 7:
# Simulate a "second machine" with a separate directory owned by this beta run
$betaDataDir2 = Join-Path $betaRunRoot 'data-2'
New-Item -ItemType Directory -Path $betaDataDir2 -ErrorAction Stop | Out-Null
# Scope these commands to the second data dir, then restore the first one
$env:ENGRAM_DATA_DIR = $betaDataDir2
try {
& $betaBinaryPath cloud enroll beta-test
& $betaBinaryPath sync --cloud --project beta-test
& $betaBinaryPath search 'Architecture' --project beta-test
} finally {
$env:ENGRAM_DATA_DIR = $betaDataDir
}# List existing conflicts
./engram-beta conflicts list --project beta-test
# Show stats
./engram-beta conflicts stats --project beta-test
# Retroactive scan (FTS5-based, no LLM yet)
./engram-beta conflicts scan --project beta-test --dry-run
./engram-beta conflicts scan --project beta-test --apply --max-insert 10
# After scan, inspect what got created
./engram-beta conflicts list --project beta-test --status pending
# Drill into a specific relation
./engram-beta conflicts show <relation_id>conflicts list and conflicts stats exclude pending relations whose source and target have known, different effective projects (observation project, falling back to the session project). The same rule applies to /conflicts results and totals and /conflicts/stats. Same-project pending relations, unknown ownership, and judged evidence retain their existing behavior. Excluded rows are not deleted or judged: inspect them with conflicts show <relation_id> or GET /conflicts/<relation_id>. Judgment guards and sync behavior are unchanged. Store relation lists (both inclusive and actionable) sort by newest created_at first, breaking ties by descending local numeric relation ID (id, not sync_id); this tie order is deterministic within a database, not guaranteed across synced or imported databases.
The HTTP API works too. The /conflicts/* routes live on the local engram serve (port 7437) — no auth required, localhost-only. Start it in a separate terminal:
# Terminal 2 (keep the same exported env vars from step 4):
./engram-beta serveWindows PowerShell 7 (a second dedicated beta window): Copy the printed $betaRunRoot value from step 4 and replace both placeholders below. This window reconstructs the same beta-only session; it does not create a new data directory or own cleanup.
$betaClonePath = 'C:\replace-with-your-path\engram-beta-repo'
$betaRunRoot = 'C:\replace-with-the-printed-beta-run-root'
Set-Location -LiteralPath $betaClonePath
$betaBinaryPath = Join-Path $betaClonePath 'engram-beta.exe'
$betaDataDir = Join-Path $betaRunRoot 'data'
if (-not (Test-Path -LiteralPath $betaBinaryPath -PathType Leaf)) {
throw "Beta binary not found: $betaBinaryPath"
}
if (-not (Test-Path -LiteralPath $betaDataDir -PathType Container)) {
throw "Beta data directory not found: $betaDataDir"
}
$env:ENGRAM_DATA_DIR = $betaDataDir
$env:ENGRAM_CLOUD_SERVER = 'http://127.0.0.1:28080'
$env:ENGRAM_CLOUD_TOKEN = 'beta-token-CHANGE-ME-please-32chars'
& $betaBinaryPath serveThen query from anywhere:
curl -s "http://127.0.0.1:7437/conflicts?project=beta-test" | jq
curl -s "http://127.0.0.1:7437/conflicts/stats?project=beta-test" | jqWindows PowerShell 7:
Invoke-RestMethod -Uri 'http://127.0.0.1:7437/conflicts?project=beta-test' | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri 'http://127.0.0.1:7437/conflicts/stats?project=beta-test' | ConvertTo-Json -Depth 10Note: this is the client-side serve (your local API), not the beta cloud. Cloud sync of relations happens in the background per Phase 2.
This is where your existing agent CLI does the work. Your subscription pays $0 extra — only quota is consumed.
# Tell engram which agent CLI to use
export ENGRAM_AGENT_CLI=claude # or opencode
# Run scan with semantic detection
./engram-beta conflicts scan --project beta-test --semantic --apply \
--max-semantic 5 --concurrency 3 --yesWindows PowerShell 7:
# Tell engram which agent CLI to use for this PowerShell session
$env:ENGRAM_AGENT_CLI = 'claude' # or 'opencode'
& $betaBinaryPath conflicts scan --project beta-test --semantic --apply `
--max-semantic 5 --concurrency 3 --yesWhat happens:
- FTS5 finds candidate pairs (lexical overlap)
- For each pair, engram shells out to your CLI:
claude -p "Compare these..."oropencode run ... - Your agent's LLM returns a verdict (relation + confidence + reasoning)
- Engram persists positive verdicts as
memory_relationswithmarked_by_kind=system
After scan:
./engram-beta conflicts stats --project beta-test
# Should show semantic counters > 0 if any candidates surfaced
./engram-beta conflicts list --project beta-test --status judged
# See the verdicts with reasoningTest the killer case — vocabulary-different conflict:
./engram-beta save \
"Use Postgres for the user database" \
"Postgres 15 is our SQL store for users and sessions." \
--type architecture --project beta-test
./engram-beta save \
"We migrated to MongoDB last quarter" \
"Document store now backs the user collection. SQL is gone." \
--type decision --project beta-test
./engram-beta conflicts scan --project beta-test --semantic --apply \
--max-semantic 5 --yesExpect supersedes or conflicts_with verdict because the LLM understands "Postgres → MongoDB" is a real disagreement, even if FTS5 alone wouldn't have flagged them.
If you have an agent connected via MCP to this beta engram:
# Point agent at beta engram MCP (in your agent config):
# command: /path/to/engram-beta-repo/engram-beta
# args: ["mcp"]
# env: { ENGRAM_DATA_DIR: /tmp/engram-beta-data }For a Windows agent configuration, generate a JSON fragment from the current beta session. It uses the exact $betaDataDir created in step 4; copy the output into the appropriate MCP configuration structure for your agent.
# Derive this run's MCP executable path; this configuration does not own cleanup.
$betaBinaryPath = Join-Path $betaClonePath 'engram-beta.exe'
$betaMcpConfig = [ordered]@{
command = $betaBinaryPath
args = @('mcp')
env = [ordered]@{
ENGRAM_DATA_DIR = $betaDataDir
}
}
$betaMcpConfig | ConvertTo-Json -Depth 3The agent will see mem_compare(memory_id_a, memory_id_b, relation, confidence, reasoning, [model]) as a new tool.
- Phase 2: did relations sync across data dirs? Any FK errors? Check
/sync/status'sdeferred_countanddead_count. - Phase 3: does
conflicts list/scanproduce sensible output? Pagination working? Stats accurate? - Phase 4: did your CLI invocation work? Did you get $0 cost (sub) or unexpected charges (API)? Did the LLM verdict make sense for the pair?
- General: any latency, hangs, weird logs, missing features.
Report at: https://github.com/Gentleman-Programming/engram/issues (tag beta-phase-2-3-4).
# Stop and DESTROY beta cloud + postgres data
docker compose -f docker-compose.beta.yml down -v
# Remove beta data dirs
rm -rf /tmp/engram-beta-data /tmp/engram-beta-data-2
# Remove the beta binary
rm -f ./engram-beta
# (Optional) Remove the cloned repo
cd .. && rm -rf engram-beta-repoWindows PowerShell 7: First, in the dedicated server window, press Ctrl+C and wait for .\engram-beta.exe serve to return to the prompt; this confirms it exited before any files are deleted. Then run the following in the original dedicated beta session. It removes only the beta Compose resources, binary under $betaClonePath, and unique run directory under $betaRunRoot.
# Stop and DESTROY beta cloud + its engram-beta-pg volume
docker compose -f docker-compose.beta.yml down -v
if ($LASTEXITCODE -ne 0) {
throw "Failed to stop the beta Compose resources."
}
# Delete the binary only when this session built it; otherwise leave it untouched.
if ($betaBinaryOwnedByThisRun -and (Test-Path -LiteralPath $betaBinaryPath -PathType Leaf)) {
Remove-Item -LiteralPath $betaBinaryPath -Force -ErrorAction Stop
}
# Remove only this run's data; deletion failures stop visibly.
if (Test-Path -LiteralPath $betaRunRoot -PathType Container) {
Remove-Item -LiteralPath $betaRunRoot -Recurse -Force -ErrorAction Stop
}
# Optional and false by default: set to $true only after preserving any changes in the beta clone
$removeBetaClone = $false
if ($removeBetaClone) {
Remove-Item -LiteralPath $betaClonePath -Recurse -Force -ErrorAction Stop
}Close both dedicated beta PowerShell windows after cleanup. Their session-scoped ENGRAM_* values are not persisted.
Your production engram setup is fully untouched. Your prod cloud, your ~/.engram/engram.db, your engram binary — none of those were modified during this test.
engram-beta cloud status shows wrong server
Check echo $ENGRAM_CLOUD_SERVER — must point at http://127.0.0.1:28080.
In PowerShell, check $env:ENGRAM_CLOUD_SERVER — it must point at http://127.0.0.1:28080.
cloud-beta container exits with auth error
The token in docker-compose.beta.yml must match ENGRAM_CLOUD_TOKEN exported in your shell. Default for both is beta-token-CHANGE-ME-please-32chars.
Phase 4 --semantic says "ENGRAM_AGENT_CLI is not set"
Export it: export ENGRAM_AGENT_CLI=claude (or opencode). The CLI must be on your PATH and authenticated.
In PowerShell: $env:ENGRAM_AGENT_CLI = 'claude' (or 'opencode'). The CLI must be on your PATH and authenticated.
Phase 4 prompt times out
Default timeout is 60s/call. Increase: --timeout-per-call 120. Or reduce concurrency: --concurrency 2.
Port 28080 already in use
Edit docker-compose.beta.yml and change 28080:28080 to a free port (and update ENGRAM_CLOUD_SERVER accordingly).