#1 Persistent memory for AI coding agents based on real-world benchmarks
This report summarizes scanner evidence for rohitg00/agentmemory, a TypeScript project with 30,047 GitHub stars. SynthScan examined 247,938 lines of code across 919 source files, recording 225 pattern matches distributed across 13 syntactic categories. The legacy adjusted pattern signal is 1.3 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 194 finding(s).
Are imports declared and package/API names verified? 18 finding(s).
Are wrappers, guards, and repeated structures necessary? 173 finding(s).
Which changes need focused human review? 225 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 225 distinct pattern matches across 13 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | benchmark/quality-eval.ts | 430 | async function evalBuiltinMemoryTruncated( | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 147 | def test_url_delimiters_fail_closed_without_rejecting_encoded_paths(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 157 | def test_plaintext_guard_uses_same_numeric_loopback_boundary(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 165 | def test_authentication_offline_and_invalid_responses_are_distinguishable(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 266 | def test_external_evolution_conflict_never_deletes_or_creates_a_competing_record(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 276 | def test_foreign_identity_response_does_not_establish_mirror_ownership(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 282 | def test_same_returned_id_is_never_deleted(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 351 | def test_invalid_tool_arguments_never_reach_network(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 358 | def test_search_failure_does_not_become_empty_success(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 366 | def test_switch_orders_end_start_turn_and_end_uses_new_session(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 375 | def test_native_session_start_shape_is_tracked_and_closed(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 400 | def test_precompress_returns_bounded_context_without_mutating_transcript(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 409 | def test_native_replace_is_mirrored_and_remove_never_guesses_shared_record_ids(self): | CODE |
| LOW⚡ | test/hermes-provider-contracts.py | 416 | def test_sync_waits_for_wire_completion_and_shutdown_waits_for_inflight_write(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 47 | def test_missing_scoped_accessor_never_falls_back_to_environment_or_files(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 57 | def test_provider_never_reads_credential_files(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 110 | def test_config_precedence_and_no_saved_credential_on_url_override(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 123 | def test_config_respects_initialize_home_and_does_not_save_secrets(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 135 | def test_malformed_config_falls_back_and_invalid_explicit_url_is_unavailable(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 180 | def test_endpoint_change_does_not_receive_a_different_endpoints_credentials(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 199 | def test_credentials_rotate_for_the_same_endpoint(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 212 | def test_routed_scope_never_falls_back_to_process_secrets_or_unscoped_profile(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 222 | def test_replacement_evolves_only_exact_owned_previous_content(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 241 | def test_mirror_ownership_survives_restart_and_failed_evolve_keeps_old_mapping(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 295 | def test_redirects_refuse_to_forward_credentials(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 301 | def test_native_save_preserves_metadata_and_search_preserves_result_identity(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 314 | def test_prefetch_expands_scoped_compact_hits_and_keeps_beyond_title_evidence(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 335 | def test_prefetch_cache_is_scoped_one_shot_and_invalidated_by_writes(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 388 | def test_failed_end_remains_retryable_and_same_session_rewind_does_not_restart(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 438 | def test_shutdown_is_bounded_and_late_writes_are_rejected(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 458 | def test_same_workspace_and_session_are_isolated_by_profile_and_survive_restart(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 480 | def test_concurrent_profiles_keep_endpoints_credentials_and_identity_bound(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 512 | def test_cross_profile_provider_and_cache_fail_closed_even_with_same_endpoint(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 531 | def test_cache_refuses_endpoint_or_identity_changes(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 542 | def test_gateway_authors_are_context_local_and_delayed_writes_keep_their_author(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 566 | def test_gateway_missing_author_never_reuses_primary_identity(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 576 | def test_nonprimary_contexts_do_not_capture_or_modify_remote_state(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 587 | def test_static_prompt_never_reads_cross_profile_project_context(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 593 | def test_empty_session_ids_are_rejected_and_empty_switch_preserves_binding(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 606 | def test_explicit_identity_is_deliberate_and_tool_overrides_are_validated(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 621 | def test_native_scoped_credentials_rotate_without_reading_process_values(self): | CODE |
| LOW | test/hermes-provider-contracts.py | 637 | def test_host_workspace_and_explicit_project_determine_scope(self): | CODE |
| LOW | test/hermes-plugin.test.ts | 48 | function readAgentMemoryProviderHookMethods(): string[] { | CODE |
| LOW | test/cli-engine-startup.test.ts | 24 | expect(source).toContain("function printCapturedStartupStderr()"); | CODE |
| LOW | test/cli-engine-startup.test.ts | 113 | expect(source).toContain("function printCapturedStartupStderr()"); | CODE |
| LOW | test/index-persistence.test.ts | 66 | async function writeLegacyVectorSnapshot( | CODE |
| LOW | test/cli-lifecycle-safety.test.ts | 64 | function runNativeRemoveWithWorkerFailure() { | CODE |
| LOW⚡ | integrations/hermes/__init__.py | 124 | def _uses_plaintext_bearer_auth(base: str, secret: str = "") -> bool: | CODE |
| LOW⚡ | integrations/hermes/__init__.py | 131 | def _plaintext_bearer_auth_message(base: str) -> str: | CODE |
| LOW⚡ | integrations/hermes/__init__.py | 135 | def _warn_plaintext_bearer_auth(message: str) -> None: | CODE |
| LOW⚡ | integrations/hermes/__init__.py | 139 | def _check_plaintext_bearer_guard( | CODE |
| LOW | integrations/hermes/__init__.py | 155 | def _reset_plaintext_bearer_guard_for_tests() -> None: | CODE |
| LOW | scripts/skills/rest-endpoints.ts | 36 | export function collectRestEndpointsInDirectory(directory: string): { path: string; method: string }[] { | CODE |
| LOW | src/cli.ts | 708 | async function startWorkerForEngineState(background = false): Promise<void> { | CODE |
| LOW | src/cli.ts | 813 | function configuredEngineMayStartWorker(): boolean { | CODE |
| LOW | src/cli.ts | 827 | async function assertRuntimePortOwnership(): Promise<void> { | CODE |
| LOW | src/cli.ts | 1080 | function printCapturedStartupStderr(): void { | CODE |
| LOW | src/cli.ts | 1431 | async function waitForPersistedNativeEngine(): Promise<boolean> { | CODE |
| LOW | src/cli.ts | 1509 | async function reconcilePersistedComposeEngine(): Promise<boolean> { | CODE |
| LOW | src/cli.ts | 2998 | async function stopNativeEngineForRemoval(): Promise<NativeRemovalStopResult> { | CODE |
| 100 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | test/compression-recovery.test.ts | 109 | expect(r.sdk.trigger.mock.calls.some(([input]) => input.function_id === "stream::send")).toBe(false); | CODE |
| CRITICAL | test/compression-recovery.test.ts | 169 | await vi.waitFor(() => expect(r.sdk.trigger.mock.calls.some(([input]) => input.function_id === "mem::compress")).toB | CODE |
| CRITICAL | test/compression-recovery.test.ts | 201 | await vi.waitFor(() => expect(r.sdk.trigger.mock.calls.some(([input]) => input.function_id === "mem::compress")).toB | CODE |
| CRITICAL | test/compression-recovery.test.ts | 218 | await vi.waitFor(() => expect(r.sdk.trigger.mock.calls.filter(([input]) => input.function_id === "mem::compress")).t | CODE |
| CRITICAL | test/compression-recovery.test.ts | 248 | await vi.waitFor(() => expect(r.sdk.trigger.mock.calls.some(([input]) => input.function_id === "mem::compress")).toB | CODE |
| CRITICAL | test/compression-recovery.test.ts | 315 | expect(r.sdk.trigger.mock.calls.some(([input]) => input.function_id === "stream::send")).toBe(false); | CODE |
| CRITICAL | test/recall-layer.test.ts | 152 | expect(f.sdk.trigger.mock.calls.some(([call]) => call.function_id === "mem::lesson-recall")).toBe(false); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | test/hermes-live-model.py | 290 | except (OSError, ValueError, subprocess.CalledProcessError): | CODE |
| HIGH | test/hermes-native-e2e.py | 384 | except (OSError, ValueError, subprocess.CalledProcessError): | CODE |
| HIGH | integrations/hermes/__init__.py | 46 | except Exception: | CODE |
| HIGH | integrations/hermes/__init__.py | 281 | except ImportError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/snapshot-config.test.ts | 1 | import { describe, it, expect, beforeEach, afterEach } from "vitest"; | COMMENT |
| LOW | test/fetch-timeout.test.ts | 481 | // We don't actually wait 60s — the provider stores timeoutMs at | COMMENT |
| LOW | scripts/backfill-imported-sessions.sh | 1 | #!/usr/bin/env bash | COMMENT |
| LOW | src/cli.ts | 561 | } catch { | COMMENT |
| LOW | src/triggers/events.ts | 81 | // Crystals + lessons consolidation. The stop lifecycle is the single | COMMENT |
| LOW | src/providers/_openai-shared.ts | 1 | // Shared transport helpers for the OpenAI-compatible LLM + embedding | COMMENT |
| LOW | src/cli/doctor-diagnostics.ts | 1 | // Doctor v2 diagnostic catalog. | COMMENT |
| LOW | src/cli/splash.ts | 1 | // Terminal-width-aware splash banner for the agentmemory CLI. | COMMENT |
| LOW | src/cli/preferences.ts | 1 | // JSON-backed CLI preferences. | COMMENT |
| LOW | src/cli/preferences.ts | 41 | // The first onboarding sets this to true so the second invocation | COMMENT |
| LOW | src/cli/onboarding.ts | 1 | // First-run interactive onboarding flow. | COMMENT |
| LOW | src/cli/remove-plan.ts | 1 | // `agentmemory remove` — destruction plan. | COMMENT |
| LOW | src/viewer/server.ts | 41 | COMMENT | |
| LOW | src/hooks/antigravity-bridge.ts | 1 | #!/usr/bin/env node | COMMENT |
| LOW | src/hooks/cursor/workspace.ts | 301 | return { name: canonicalProject(gitRootFromPath(targetPath)), fromGitRoot: true }; | COMMENT |
| LOW | src/hooks/cursor/workspace.ts | 401 | // | COMMENT |
| LOW | src/hooks/cursor/workspace.ts | 441 | if (++scanned > TRANSCRIPT_MATCH_LIMIT) break; | COMMENT |
| LOW | src/functions/remember.ts | 81 | ? data.agentId.trim().slice(0, 128) | COMMENT |
| LOW | src/functions/search.ts | 181 | // inside the 5s debounce window would lose deletes and resurrect | COMMENT |
| LOW | src/functions/export-import.ts | 41 | import { VERSION } from "../version.js"; | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | test/fetch-timeout.test.ts | 29 | // ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | test/fetch-timeout.test.ts | 31 | // ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | test/fetch-timeout.test.ts | 77 | // ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | test/fetch-timeout.test.ts | 83 | // ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | test/fetch-timeout.test.ts | 317 | // ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | test/fetch-timeout.test.ts | 321 | // ───────────────────────────────────────────────────────────── | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | website/lib/generated-changelog.json | 50 | "body": "Stability + ecosystem wave. Three install-broken bugs (`npm install` ERESOLVE, non-OpenAI base URLs, broken | CODE |
| MEDIUM⚡ | website/lib/generated-changelog.json | 55 | "body": "Quality + integration wave. Headline: native OpenCode plugin with full Claude Code hook parity ([#237](http | CODE |
| MEDIUM | docs/recipes/pairings.md | 40 | ## [Understand Anything](https://github.com/Lum1104/Understand-Anything) — multi-agent code-graph pipeline + dashboard | COMMENT |
| MEDIUM | READMEs/README.he-IL.md | 1076 | ### זיכרון multi-agent (`AGENT_ID` + `AGENTMEMORY_AGENT_SCOPE`) | COMMENT |
| MEDIUM | READMEs/README.fr-FR.md | 1082 | ### Mémoire multi-agent (`AGENT_ID` + `AGENTMEMORY_AGENT_SCOPE`) | COMMENT |
| MEDIUM | READMEs/README.ro-RO.md | 1069 | ### Memorie multi-agent (`AGENT_ID` + `AGENTMEMORY_AGENT_SCOPE`) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | benchmark/capture-costs.ts | 971 | OPENAI_API_KEY: "bench-fake-key", | CODE |
| LOW | test/viewer-host.test.ts | 230 | process.env.VIEWER_ALLOWED_HOSTS = "placeholder"; | CODE |
| LOW | test/viewer-host.test.ts | 277 | process.env.VIEWER_ALLOWED_HOSTS = "placeholder"; | CODE |
| LOW | test/schema.test.ts | 50 | jaccardSimilarity('the quick brown fox', 'lorem ipsum dolor sit'), | CODE |
| LOW | test/temporal-graph.test.ts | 78 | <entity type="organization" name="Acme Corp"> | CODE |
| LOW | test/temporal-graph.test.ts | 83 | <relationship type="works_at" source="Alice" target="Acme Corp" weight="0.9" valid_from="2024-01-01" valid_to="curre | CODE |
| LOW | test/temporal-graph.test.ts | 146 | name: "Acme Corp", | CODE |
| LOW | test/temporal-graph.test.ts | 170 | <entity type="organization" name="Acme Corp"> | CODE |
| LOW | test/temporal-graph.test.ts | 174 | <relationship type="works_at" source="Alice" target="Acme Corp" weight="0.95" valid_from="2025-01-01" valid_to="curr | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/hermes-live-model.py | 56 | CODE | |
| LOW | test/hermes-live-model.py | 116 | CODE | |
| LOW | test/hermes-native-e2e.py | 170 | CODE | |
| LOW | test/hermes-native-e2e.py | 271 | CODE | |
| LOW | integrations/hermes/__init__.py | 598 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | website/lib/generated-changelog.json | 50 | "body": "Stability + ecosystem wave. Three install-broken bugs (`npm install` ERESOLVE, non-OpenAI base URLs, broken | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/hermes-live-model.py | 127 | except Exception: | CODE |
| LOW | test/hermes-native-e2e.py | 283 | except Exception: | STRING |
| LOW | integrations/hermes/__init__.py | 46 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/hermes-live-model.py | 4 | CODE | |
| LOW | integrations/hermes/__init__.py | 9 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | test/summarize.test.ts | 426 | }) + "\n```\nLet me know if you need anything else."; | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/backfill-imported-sessions.sh | 17 | # Usage: | COMMENT |