How to Use Graphify Reflection for Stale Data Detection and Recovery

Graphify reflection generates a .graphify_learning.json side-car that marks lessons as stale when source code fingerprints (SHA-256 hashes) no longer match current files, enabling automated detection of outdated knowledge.

Graphify (Graphify-Labs/graphify) is an open-source knowledge management tool that converts Q&A memory into deterministic lessons. Its reflection engine tracks code changes to identify when cached knowledge becomes stale, allowing agents to ignore outdated advice or trigger regeneration.

How Graphify Reflection Detects Stale Data

The reflection process in graphify/reflect.py transforms memory documents into a structured learning overlay. It fingerprints source files to detect when lesson content no longer reflects the current implementation.

The Reflection Pipeline

The reflection pipeline executes six distinct steps to generate lessons and detect staleness:

  1. Collect memory docs – load_memory_docs parses every *.md file containing front-matter written by graphify save-result (lines 33-57) in graphify/reflect.py.
  2. Aggregate lessons – aggregate_lessons scores each source node with time-decayed weights, grouping them into preferred, tentative, and contested buckets while recording provenance events (lines 64-78).
  3. Render the lessons file – render_lessons_md produces a stable markdown document at graphify-out/reflections/LESSONS.md (lines 90-110).
  4. Build the learning side-car – build_learning_overlay resolves each node to a canonical ID and adds a code_fingerprint (SHA-256 hash of the node's source file) via _content_hash (lines 672-679).
  5. Write the side-car – write_learning_sidecar writes .graphify_learning.json beside the graph in a deterministic, sorted format (lines 331-338).
  6. Detect staleness – The _is_stale function (lines 687-699) compares stored fingerprints against current file hashes.

The Learning Side-Car Structure

The .graphify_learning.json file contains metadata for each node referenced in the lessons:

  • code_fingerprint: SHA-256 hash of the source file content at the time of reflection
  • stale: Boolean flag indicating whether the implementation has changed
  • source_file: Path to the source file (resolved via _resolve_source_path)
  • generated_at: Timestamp of lesson creation

This side-car is generated by build_learning_overlay and written atomically to prevent corruption during concurrent access.

The Staleness Check Algorithm

When load_learning_overlay loads the side-car, it invokes _is_stale to validate each entry:

  • _resolve_source_path (lines 668-682) handles absolute paths, layout-specific roots, and the optional .graphify_root marker to locate the current source file.
  • The function recomputes the SHA-256 hash of the current file and compares it with the stored code_fingerprint.
  • If the file is missing, the hash differs, or no fingerprint was recorded, the entry is marked stale (lines 687-699).

Detecting Stale Data Programmatically

You can consume the reflection artifacts in Python to build staleness-aware workflows.

Loading the Side-Car with load_learning_overlay

Import load_learning_overlay from graphify.reflect to access the staleness metadata:

from pathlib import Path
from graphify.reflect import load_learning_overlay

graph_path = Path("graphify-out/graph.json")
learning = load_learning_overlay(graph_path)

# Returns a dict: node_id → entry dict

print(f"Loaded {len(learning)} lesson entries")

Each entry contains the stale boolean, code_fingerprint, and source_file path.

Filtering Stale Entries

Filter the overlay to identify outdated lessons that require attention:


# Filter for stale entries only

stale_nodes = {
    nid: entry for nid, entry in learning.items() 
    if entry.get("stale")
}

print(f"Found {len(stale_nodes)} stale lessons:")
for nid, entry in stale_nodes.items():
    print(f"- {entry['label']} (id={nid}) – last updated {entry['generated_at']}")

This pattern allows agents to exclude stale guidance from prompt context or flag them for review.

Refreshing Stale Lessons

When stale data is detected, you can regenerate the lessons using either the CLI or the Python API.

CLI Workflow

Run reflection from the command line to regenerate the lessons file and side-car:

graphify reflect --memory graphify-out/memory \
               --out graphify-out/reflections/LESSONS.md \
               --graph graphify-out/graph.json \
               --if-stale   # skips work if output is already fresh

The --if-stale flag optimizes performance by checking modification times before recomputing. The command reads memory docs, aggregates lessons, writes LESSONS.md, and produces .graphify_learning.json beside the graph.

Programmatic Refresh with lessons_fresh

Use the Python API to conditionally refresh only when necessary:

from pathlib import Path
from graphify.reflect import reflect, lessons_fresh

memory_dir = Path("graphify-out/memory")
out_path = Path("graphify-out/reflections/LESSONS.md")
graph_path = Path("graphify-out/graph.json")

# Re-run only if source files changed

if not lessons_fresh(out_path, memory_dir, graph_path=graph_path):
    reflect(memory_dir, out_path, graph_path=graph_path)
    print("Lessons refreshed – stale data updated.")
else:
    print("Lessons are up-to-date.")

The lessons_fresh function checks file modification times, while the side-car provides content-hash verification for cryptographic certainty.

Summary

  • Graphify reflection produces a deterministic LESSONS.md artifact and a .graphify_learning.json side-car containing SHA-256 fingerprints for every source node.
  • Stale detection occurs in _is_stale (lines 687-699 of graphify/reflect.py), which compares stored fingerprints against current file hashes using _resolve_source_path.
  • Programmatic access via load_learning_overlay returns a dictionary where the stale boolean flag indicates outdated entries.
  • Conditional regeneration uses lessons_fresh to avoid unnecessary computation, while the --if-stale CLI flag provides similar optimization for shell workflows.

Frequently Asked Questions

What does "stale data" mean in Graphify?

In Graphify, stale data refers to a lesson whose associated source code has been modified or deleted after the lesson was generated. The reflection engine stores a SHA-256 fingerprint of each source file; when load_learning_overlay detects a hash mismatch or missing file via _is_stale, it marks the entry as stale to prevent agents from relying on outdated guidance.

How does Graphify track code changes for staleness?

Graphify tracks changes through content hashing rather than timestamps. During reflection, build_learning_overlay computes a code_fingerprint (SHA-256 hash) for each node's source file (lines 672-679 in graphify/reflect.py). When loading the overlay, _is_stale recomputes the hash and compares it to the stored fingerprint, marking the entry stale if they differ or if the file is missing.

Can I skip reflection if lessons are already fresh?

Yes. Use the --if-stale flag in the CLI to skip processing when outputs are current, or call lessons_fresh(out_path, memory_dir, graph_path=graph_path) in Python to check modification times before invoking reflect. This prevents unnecessary I/O when source files and memory documents haven't changed since the last run.

Where is the stale data metadata stored?

The staleness metadata is stored in .graphify_learning.json, a JSON side-car file written beside your graph file (e.g., graphify-out/graph.json). This file is generated by write_learning_sidecar (lines 331-338) and contains the code_fingerprint, stale boolean, and source_file path for each lesson entry.

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 →