How to Use `memory_lint` to Find Contradictions in AI Memory Wikis

memory_lint is the linting subsystem of ai-memory that scans wiki pages for contradictions, stale claims, and logical errors using both rule-based checks and optional LLM-driven analysis.

The memory_lint system in the akitaonrails/ai-memory repository helps developers maintain coherent knowledge bases by automatically detecting when memory pages contain conflicting information. This guide explains how to run contradiction detection from the CLI, integrate linting into Rust applications, and interpret the generated reports.

Two-Layer Linting Architecture

memory_lint operates through complementary detection layers that can run independently or together.

Rule-Based Checks (Always Active)

These fast, deterministic validations flag structural and metadata problems:

  • Stale episodic pages exceeding their decay threshold
  • Empty page bodies
  • Duplicate titles across the wiki
  • Pinned pages with contradictory expiration dates
  • Pages that appear to be durable rules but lack proper tagging

LLM-Driven Contradiction Detection (Opt-In)

When a language model provider is configured, memory_lint performs deeper semantic analysis. The system:

  1. Identifies up to 20 high-access semantic or procedural pages (configurable via LLM_CLUSTER_CAP)
  2. Builds a structured prompt with page previews
  3. Sends the prompt to the LLM via complete_structured
  4. Parses the JSON response into a LintReport containing contradictions and stale claims

Running memory_lint from the Command Line

The CLI interface lives in crates/ai-memory-cli/src/commands/lint.rs and provides three invocation patterns.

Basic Lint with LLM Contradiction Detection

ai-memory lint --workspace my_ws --project my_proj

This triggers the full two-layer analysis and writes findings to wiki/_lint/<YYYY-MM-DD>.md.

Dry-Run Mode (No File Output)

ai-memory lint --dry-run

Use this to preview findings without persisting the report.

Rule-Based Only (Skip LLM)

ai-memory lint --no-llm

Disable the LLM pass when you need fast feedback or lack API credits.

Programmatic Integration in Rust

For embedding memory_lint into larger applications, import run_lint from ai-memory-consolidate and construct a LintOptions configuration.

use ai_memory_consolidate::{run_lint, LintOptions};
use ai_memory_store::ReaderPool;
use ai_memory_wiki::Wiki;
use std::sync::Arc;
use ai_memory_llm::LlmProvider;

async fn lint_my_project(
    reader: &ReaderPool,
    wiki: &Wiki,
    llm: Option<Arc<dyn LlmProvider>>
) {
    let opts = LintOptions {
        dry_run: false,
        use_llm: true,
        decay_lambda: 0.02,
    };
    
    let report = run_lint(
        reader,
        wiki,
        llm.as_ref(),
        workspace_id,
        project_id,
        opts
    )
    .await
    .expect("lint failed");
    
    println!("Found {} issue(s)", report.findings.len());
}

The run_lint function in crates/ai-memory-consolidate/src/lint.rs (lines 43-56) orchestrates the full pipeline: gathering decay candidates, executing rule_based_findings, and conditionally invoking contradiction_pass.

How the Contradiction Pass Works

The LLM-driven analysis in contradiction_pass (lines 66-84) follows a precise data flow:

  1. Page Selection — Ranks pages by access frequency, caps at LLM_CLUSTER_CAP (20)
  2. Prompt Construction — Embeds page content with the system prompt from crates/ai-memory-consolidate/prompts/lint_system.md
  3. Structured Completion — Calls complete_structured from ai-memory-llm for JSON output
  4. Report Deserialization — Parses into LintReport structs (defined lines 35-62)
  5. Finding Merge — Combines with rule-based results

The system prompt enforces security boundaries and output format constraints, preventing prompt injection while ensuring parseable results.

Understanding Lint Reports

Reports are written by write_report_page (lines 14-48) to markdown files in wiki/_lint/. Here's a sample contradiction finding:


# Lint findings

2 finding(s).

## 1 — contradiction (warning)

Episodic page `sessions/2024-09-30.md` claims "The server runs on port 8080", but another page asserts "The server always uses port 80".

Pages:
- `sessions/2024-09-30.md`
- `concepts/server-port.md`

Store these reports in version control to track knowledge base health over time. The markdown format supports grepping for specific issue types or affected pages.

Key Source Files

File Purpose
crates/ai-memory-consolidate/src/lint.rs Core run_lint entry point, contradiction_pass, rule_based_findings, write_report_page
crates/ai-memory-cli/src/commands/lint.rs CLI argument parsing and HTTP client for ai-memory lint command
crates/ai-memory-consolidate/prompts/lint_system.md LLM system prompt with security boundaries and output schema
crates/ai-memory-wiki/src/lib.rs Wiki::write_page implementation for persisting reports
crates/ai-memory-llm/src/lib.rs LlmProvider trait and complete_structured helper

Summary

  • memory_lint combines rule-based and LLM analysis to detect contradictions in ai-memory wikis
  • CLI usage: ai-memory lint with --dry-run or --no-llm flags for flexible execution
  • Programmatic usage: Import run_lint and LintOptions from ai-memory-consolidate
  • Reports land in wiki/_lint/<date>.md with structured markdown for version control review
  • Key constant: LLM_CLUSTER_CAP = 20 limits pages sent to the LLM for cost control

Frequently Asked Questions

What types of contradictions can memory_lint detect?

memory_lint finds logical contradictions (conflicting facts about the same entity), temporal inconsistencies (outdated claims in newer pages), and rule violations (pages violating declared durable rules). The LLM pass specifically targets semantic conflicts that rule-based checks cannot identify, such as "the API uses REST" versus "the API uses GraphQL exclusively."

Does memory_lint require an LLM provider to work?

No. Rule-based checks run without any LLM configuration. However, contradiction detection requires a configured provider. Pass --no-llm to skip the LLM pass entirely, or ensure your environment has a valid LLM provider set up for ai-memory-llm to use with complete_structured.

How does memory_lint decide which pages to analyze for contradictions?

The contradiction_pass function ranks pages by access frequency (recent and frequent reads indicate high relevance) and selects the top LLM_CLUSTER_CAP entries—defaulting to 20. This prioritizes actively-used knowledge over archival content, keeping LLM costs predictable while surfaces likely sources of user-facing contradictions.

Can I customize the lint output location or format?

The report path wiki/_lint/<YYYY-MM-DD>.md is currently hardcoded in write_report_page at lines 14-48 of lint.rs. The markdown format is standardized to support consistent parsing. For custom integrations, call run_lint programmatically and process the returned LintReport struct directly before it reaches write_report_page.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →