Your Code Knows What Changed. But Does It Know Why? A developer argues that AI-assisted software engineering faces a growing challenge: while writing code is becoming cheaper, understanding why code exists is not. The developer proposes an 'Engineering Graph' that connects pull requests, commits, files, services, deployments, incidents, fixes, and engineers to reveal the rationale behind code changes, helping engineers avoid breaking production systems. AI can write a pull request in seconds. But when that pull request touches a piece of code written three years ago, there is a much harder question: Why does this code exist? That answer might be buried across 47 commits, 12 pull requests, an old incident, a Slack conversation nobody remembers, and one engineer who left the company six months ago. This is becoming one of the biggest problems in AI-assisted software engineering. Because writing code is getting cheaper. Understanding code is not. Consider this: if user.isLegacy && featureEnabled { return fallback ; } Looks suspicious. Maybe it's dead code. Maybe someone forgot to clean it up. So an AI coding agent suggests: - if user.isLegacy && featureEnabled { - return fallback ; - } The tests pass. The PR looks clean. You merge it. Three hours later, production breaks for a subset of customers. Now you're asking a very different question: Who knew why that code was there? The answer might have been hiding in the engineering history. Git is incredible. It can tell you: What changed? Who changed it? When did they change it? But those aren't always the questions engineers need answered. We need: Why did it change? What problem was it solving? What depends on it? What happens if I change it? Has this failed before? Who understands this part of the system? Was this introduced because of an incident? What happened the last time someone touched it? The problem isn't that this information doesn't exist. It does. It's just fragmented. Every engineering organization already has a graph. They just don't usually call it one. A pull request is connected to commits. Commits are connected to files. Files are connected to services. Services are connected to deployments. Deployments are connected to incidents. Incidents are connected to fixes. Fixes are connected to engineers. Engineers are connected to decisions. Decisions are connected to outcomes. Like this: ┌────────────┐ │ Issue │ └─────┬──────┘ │ solved by │ ▼ ┌────────────┐ │ PR │ └─────┬──────┘ │ modified │ ▼ ┌────────────┐ │ Code │ └─────┬──────┘ │ depends on │ ▼ ┌────────────┐ │ Service │ └─────┬──────┘ │ affected │ ▼ ┌────────────┐ │ Incident │ └─────┬──────┘ │ caused │ ▼ ┌────────────┐ │ Fix │ └────────────┘ The valuable information isn't just the nodes. It's the edges. Suppose you're looking at: checkout.ts A traditional code search might tell you: checkout.ts ├── imported by payment.ts ├── imported by cart.ts └── imported by order.ts Useful. But an Engineering Graph could tell you: checkout.ts │ ├── modified by PR 842 │ ├── solved issue 421 │ ├── reviewed by Maya │ └── followed incident 91 │ ├── depends on retry.ts │ └── introduced after checkout timeout │ ├── affects payment-service │ └── changed 7 times during payment incidents Now you aren't just looking at code. You're looking at the story of the code . And that story can change the decision you make. This is where things get interesting. Imagine asking an AI agent: "Can I remove this retry?" With only the source code, it might respond: "The retry appears redundant and could potentially be removed." That's not useful. Now give it the engineering context: retry.ts ↓ used by checkout.ts ↓ introduced in PR 842 ↓ PR linked to checkout timeout 421 ↓ incident 91 involved the same request path ↓ three subsequent PRs modified retry behavior Now the answer could be: "I would not remove it yet. This retry mechanism was introduced to address a checkout timeout and has been modified several times after production issues. I'd inspect incident 91 and the related PRs before changing it." Same model. Different context. Better context → better reasoning. That's the fundamental idea. You don't need a giant infrastructure project to understand the architecture. Start with a tiny graph. type NodeType = | "file" | "commit" | "pull request" | "issue" | "service" | "incident" | "person"; type Relationship = | "MODIFIED" | "SOLVED" | "DEPENDS ON" | "AUTHORED BY" | "REVIEWED BY" | "AFFECTED" | "CAUSED"; Our nodes: type Node = { id: string; type: NodeType; name: string; metadata?: Record