Target Duration: 2–4 minutes (~300–450 spoken words)
Focus: Pointwise verbal delivery covering regex stack frame extraction, interval containment matching, the backwards `.endswith()` path resolution bug, hybrid frame-plus-semantic context gathering, and root-cause synthesis.
Opening & Scope:
"In this subsystem (sherlock/router.py:36 (diagnose)), I designed an automated error diagnosis engine that parses raw execution stack traces, maps crashed line numbers back to their exact AST chunks, and orchestrates root-cause diagnosis through local LLM synthesis."
Step 1: The Problem with Naive Error RAG:
"Most RAG coding assistants treat pasted error logs as plain text, passing the entire traceback into a vector embedding model. This fails because compiler and interpreter stack traces are dense with boilerplate, absolute filesystem paths, and library frames. Vector search alone rarely surfaces the actual line of application code where the exception occurred."
Step 2: Dual Regex Stack Frame Parsing:
"In parse_frames() (router.py:21), I implemented a multi-stage regex extractor:
PY_FRAME_RE (File "([^"]+)", line (\d+)) to extract Python stack traces.GENERIC_FRAME_RE (([^\s():]+\.\w+):(\d+)) to parse GCC compiler errors, Node.js traces, and Go panics.(file, line) coordinates."Step 3: Interval Containment Line Matching:
"Once the executing (file, line) tuples are parsed, Sherlock locates the exact enclosing function in router.py:45. Because each indexed chunk stores physical boundaries (start_line and end_line), the router evaluates interval containment: r["start_line"] <= line <= r["end_line"]. This pulls the exact function that crashed, providing complete syntactic context rather than just a detached single line."
Step 4: The Backwards Path Suffix Bug:
"A critical bug arose during early testing: tracebacks use absolute paths like /Users/.../app.py, while the index stores relative paths like app.py. The code originally ran r["file"].endswith(file)—checking if the short path ended with the long path—which failed 100% of the time! I diagnosed and resolved this by reversing the evaluation to file.endswith(r["file"])."
Step 5: Hybrid Context & Root-Cause Synthesis:
"Finally, in router.py:49, Sherlock extracts the terminal exception line (e.g. ZeroDivisionError: division by zero) and executes a supplementary vector search for semantically related code. Combining the executing frame chunks with semantic neighbor chunks, it prompts Ollama with a strict directive in SYSTEM_PROMPT: identify the root cause first, then suggest a concrete fix."
| Step | What Was Done | How It Works | Why This Mechanism / Order | Code Reference |
|---|---|---|---|---|
| 1. Frame Extraction | Parse file and line numbers from text | Regex match with PY_FRAME_RE and GENERIC_FRAME_RE |
Extracts ordered call stack from pasted terminal output | router.py:21-33 |
| 2. Suffix Path Match | Normalize absolute vs relative paths | file.endswith(r["file"]) |
Matches long runtime paths (/var/log/.../app.py) against relative repo paths (app.py) |
router.py:45 |
| 3. Interval Matching | Locate chunk enclosing the failure line | r["start_line"] <= line <= r["end_line"] |
Retrieves the entire crashing function/class context, not just an isolated line | router.py:45 |
| 4. Error Line Semantic Search | Vector search on exception message | semantic_search(repo_root, error_line, k=5) |
Surfaces callers or configuration files related to the specific error message | router.py:49-50 |
| 5. Grounded Diagnosis | Synthesize fix via local LLM | answer.synthesize() with root-cause prompt |
Enforces diagnosis discipline: pinpoint root cause before proposing code changes | cli.py:68 |
# Exact stack frame resolution in router.py
def diagnose(repo_root: Path, traceback_text: str, k: int = 5) -> dict:
frames = parse_frames(traceback_text)
frame_chunks = []
# 1. Deterministic stack frame interval match
for file, line in frames:
table = indexer.open_table(repo_root)
rows = table.search().to_list()
matches = [
r for r in rows
if file.endswith(r["file"]) and r["start_line"] <= line <= r["end_line"]
]
frame_chunks.extend(matches)
# 2. Semantic vector search on exception description
error_line = traceback_text.strip().splitlines()[-1] if traceback_text.strip() else ""
semantic = indexer.semantic_search(repo_root, error_line, k=k) if error_line else []
return {
"type": "diagnose",
"frames": frames,
"frame_chunks": frame_chunks,
"semantic_chunks": semantic,
}
In early testing of sherlock diagnose, feeding valid Python tracebacks produced zero matched stack frames. The CLI repeatedly reported:
-- matched stack frames --
(empty)
-- semantically related --
...
Inspecting the frame matching logic revealed:
# BUGGY ORIGINAL LINE:
r["file"].endswith(file.lstrip("./"))
In this comparison:
r["file"] was the indexed relative path: "app.py"file was the traceback path extracted by regex: "/Users/angshuman/git/test_project/app.py""app.py".endswith("/Users/.../app.py") is mathematically impossible because the string being checked is shorter than the suffix argument! The comparison was directionally inverted.
Reversed the comparison argument in router.py:45 to:
file.endswith(r["file"])
Now, the absolute traceback path "/Users/.../app.py" correctly matches when ending with the indexed relative path "app.py". All stack frames resolved instantly.
Answer: The stack trace identifies where the program crashed, but often the root cause originated elsewhere (e.g. an invalid config loaded at startup, or a caller passing unvalidated None). Frame interval matching guarantees you retrieve the exact crashed function, while semantic search on the exception message (e.g., "KeyError: 'timeout'") retrieves configuration loaders, dictionary definitions, or upstream callers that handle timeouts.
site-packages?"Answer: Because .venv, site-packages, and Python standard libraries are excluded from the repository index by SKIP_DIRS, file.endswith(r["file"]) simply yields no match for library frames. Only the stack frames corresponding to first-party application code are matched, filtering out external framework noise and focusing the LLM's context window entirely on the user's code.