Initial POC: Developer Intelligence knowledge graph
- SQLite backend with file/repo/relationship entities - tree-sitter Go AST parser for deterministic import detection - Ollama doc generation with concurrent batch processing - MCP server (FastMCP) for Claude Code integration - Merge simulation with staleness cascade - Lazy refresh for stale relationship and repo docs - CLAUDE.md for agent context
This commit is contained in:
99
simulate_merge.py
Normal file
99
simulate_merge.py
Normal file
@@ -0,0 +1,99 @@
|
||||
"""Simulate a merge: modify a file, regenerate its doc, mark downstream stale."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
from db import GraphDB
|
||||
from docgen import generate_file_doc
|
||||
|
||||
REPO_DIR = os.environ.get("REPO_DIR", os.path.join(os.path.dirname(__file__), "repos", "target"))
|
||||
|
||||
|
||||
def simulate_merge(file_path: str, new_content: str = None):
|
||||
db = GraphDB()
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"Simulating merge: {file_path}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
# Get current doc (before)
|
||||
f = db.get_file(file_path)
|
||||
if not f:
|
||||
print(f"ERROR: File {file_path} not found in graph")
|
||||
db.close()
|
||||
return
|
||||
|
||||
print(f"\n[BEFORE] Documentation for {file_path}:")
|
||||
print(f" {f['documentation'][:300]}")
|
||||
|
||||
# Read file content (or use provided)
|
||||
if new_content is None:
|
||||
full_path = os.path.join(REPO_DIR, file_path)
|
||||
if os.path.exists(full_path):
|
||||
with open(full_path) as fh:
|
||||
original = fh.read()
|
||||
new_content = original + """
|
||||
|
||||
// EnableTracing adds distributed request tracing with correlation IDs
|
||||
// across the middleware chain. Each request gets a unique trace ID propagated
|
||||
// through all handlers for end-to-end debugging in microservice architectures.
|
||||
func (e *Echo) EnableTracing(correlationHeader string) {
|
||||
e.tracingEnabled = true
|
||||
e.correlationHeader = correlationHeader
|
||||
}
|
||||
"""
|
||||
else:
|
||||
print(f"ERROR: File not found on disk: {full_path}")
|
||||
db.close()
|
||||
return
|
||||
|
||||
# Regenerate doc for changed file
|
||||
print(f"\n[MERGE] Regenerating documentation for {file_path}...")
|
||||
new_doc = generate_file_doc(file_path, new_content)
|
||||
|
||||
commit_hash = f"sim-{int(time.time())}"
|
||||
db.update_file_doc(file_path, new_doc, commit_hash)
|
||||
|
||||
print(f"\n[AFTER] Documentation for {file_path}:")
|
||||
print(f" {new_doc[:300]}")
|
||||
|
||||
# Mark downstream stale
|
||||
print(f"\n[CASCADE] Marking downstream as stale...")
|
||||
db.mark_relationships_stale(file_path)
|
||||
|
||||
repo = db.get_repo()
|
||||
if repo:
|
||||
db.mark_repo_stale(repo["name"])
|
||||
print(f" Repo '{repo['name']}' marked stale")
|
||||
|
||||
stats = db.get_stats()
|
||||
print(f" Stale relationships: {stats['stale_relationships']}")
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print("Merge simulation complete.")
|
||||
print(f" File doc: REGENERATED (fresh)")
|
||||
print(f" Relationships: STALE (awaiting refresh)")
|
||||
print(f" Repo doc: STALE (awaiting refresh)")
|
||||
print(f"\nRun: python refresh_stale.py")
|
||||
print(f"Or ask Claude Code — stale docs show [STALE] indicator.")
|
||||
print(f"{'='*60}")
|
||||
|
||||
db.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python simulate_merge.py <file_path>")
|
||||
print("Example: python simulate_merge.py echo.go")
|
||||
sys.exit(1)
|
||||
|
||||
target = sys.argv[1]
|
||||
content = None
|
||||
if len(sys.argv) > 2:
|
||||
with open(sys.argv[2]) as f:
|
||||
content = f.read()
|
||||
|
||||
simulate_merge(target, content)
|
||||
Reference in New Issue
Block a user