cd /news/developer-tools/your-code-knows-what-changed-but-doe… Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-115766] src=dev.to β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

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.

read10 min views3 publishedAug 30, 2026

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<string, unknown>;
};

And edges:

type Edge = {
  from: string;
  to: string;
  relationship: Relationship;
  metadata?: Record<string, unknown>;
};

Now we can represent:

const edges: Edge[] = [
  {
    from: "pr:842",
    to: "file:checkout.ts",
    relationship: "MODIFIED",
  },
  {
    from: "pr:842",
    to: "issue:421",
    relationship: "SOLVED",
  },
  {
    from: "file:checkout.ts",
    to: "file:retry.ts",
    relationship: "DEPENDS_ON",
  },
  {
    from: "incident:91",
    to: "service:checkout",
    relationship: "AFFECTED",
  },
];

That's already enough to start answering questions that plain text search struggles with.

Now put an AI agent on top.

A traditional agent looks something like:

Goal
 ↓
Observe
 ↓
Decide
 ↓
Act
 ↓
Check
 ↓
Repeat

Useful.

But it starts every task with roughly the same level of ignorance.

Give it the graph:

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚        Goal          β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               ↓
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    Query Graph       β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               ↓
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚      Observe         β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               ↓
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚       Decide         β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               ↓
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚       Execute        β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               ↓
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚       Verify         β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               ↓
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    Update Graph      β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               └──────→ Next task

Now the agent doesn't just observe the repository.

It observes what happened before.

This distinction is easy to miss.

We normally think an AI system improves like this:

Better model
     ↓
More training
     ↓
Better weights
     ↓
Better performance

But agents have another path:

Better experience
       ↓
Better graph
       ↓
Better context
       ↓
Better decisions
       ↓
Better experience

The underlying model doesn't have to change.

The environment around the model improves.

That's powerful.

We shouldn't blindly turn agent activity into permanent knowledge.

Imagine an agent tries:

Increase retry count: 2 β†’ 10

The test passes.

The agent records:

"10 retries fixes checkout."

Next week another agent sees that "knowledge" and does the same thing.

Now you've created a feedback loop that makes the system confidently worse.

That's why learning systems need evidence.

Instead of:

Agent says it worked.

Store:

Code changed
    ↓
Unit tests passed
    ↓
Integration tests passed
    ↓
PR merged
    ↓
Deployment succeeded
    ↓
No incident followed

Now your graph can represent:

type Outcome = {
  status: "success" | "failure";
  confidence: number;
  evidence: string[];
};

For example:

const outcome: Outcome = {
  status: "success",
  confidence: 0.92,
  evidence: [
    "unit tests passed",
    "integration tests passed",
    "pull request merged",
    "deployment succeeded",
  ],
};

The system isn't just remembering.

It's remembering why it believes something.

That difference becomes enormous at scale.

An agent might make 50 observations while solving one problem.

We shouldn't permanently promote all 50 into "truth."

There are levels:

Observation
     ↓
Evidence
     ↓
Repeated pattern
     ↓
Validated relationship
     ↓
Reusable knowledge
     ↓
Heuristic

For example:

checkout.ts imports retry.ts
PR #842 modified checkout.ts
Tests passed after the change.
checkout.ts frequently changes with retry.ts.
When checkout timeout tests fail,
inspect retry behavior first.

That's a much safer learning architecture than dumping every agent thought into a vector database.

This might be the most underrated part.

Suppose an agent tries two approaches:

Task: Fix checkout timeout

Approach A
    ↓
FAILED

Approach B
    ↓
SUCCEEDED

A normal system might only remember B.

A learning system should remember both.

Task
β”‚
β”œβ”€β”€ attempted β†’ Approach A
β”‚                 └── FAILED
β”‚
└── attempted β†’ Approach B
                  └── SUCCEEDED

That's negative knowledge.

The next agent doesn't have to walk into the same wall.

It can know:

"This approach was already tried. It failed."

The graph remembers the dead ends.

RAG is incredibly useful.

But RAG and an Engineering Graph solve different problems.

RAG asks:

What information is relevant to this question?

A graph can ask:

How are these things related?

Imagine asking:

Why is checkout.ts high risk?

A document retriever might find:

PR #842
PR #811
PR #743

A graph can reconstruct:

checkout.ts
β”‚
β”œβ”€β”€ modified by PR #842
β”‚      β”œβ”€β”€ authored by Maya
β”‚      └── reviewed by Bobby
β”‚
β”œβ”€β”€ related to retry.ts
β”‚
β”œβ”€β”€ affected checkout-service
β”‚
└── connected to incident #91
       └── caused by previous checkout change

That's not just retrieval.

That's contextual reasoning over relationships.

And the two technologies work beautifully together:

                 User Question
                       ↓
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  Semantic Searchβ”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      ↓
              Relevant entities
                      ↓
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Graph Traversalβ”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      ↓
               Relationships
                      ↓
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚      LLM       β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      ↓
             Evidence-backed answer

This is where the idea gets really interesting.

Imagine your engineering graph continuously absorbs:

GitHub
   ↓
Commits
   ↓
Pull Requests
   ↓
Code
   ↓
Services
   ↓
Deployments
   ↓
Incidents
   ↓
Fixes
   ↓
Agent Experiences

Then add:

Jira
Slack
Confluence
Datadog
Architecture decisions
Human feedback

Eventually you're not building another code search engine.

You're building a living model of how the engineering organization works.

You can ask:

Why was this architecture chosen?

Who understands this service?

What usually breaks when we change it?

Which files are high risk?

What has already been tried?

Which engineers solved similar problems?

What happened after the last deployment?

What should an AI agent inspect before touching this service?

Those answers don't exist in any single system.

They emerge from the connections between systems.

Here's the part I think matters most.

AI is making software creation dramatically faster.

That's great.

But it creates a new bottleneck:

understanding.

If AI can generate 10x more code, we need tools that help engineers understand 10x more software.

Otherwise we're just accelerating the production of systems nobody fully understands.

The next generation of engineering tools won't just answer:

"What does this code do?"

They'll answer:

"Why is it here, what does it connect to, what happened before, and what happens if I change it?"

That's a much harder problem.

And a much more valuable one.

I think the architecture eventually becomes surprisingly simple:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               AGENTS                β”‚
β”‚        Reason β€’ Plan β€’ Act          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              CONTEXT                β”‚
β”‚       Search β€’ Retrieval β€’ RAG       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚        ENGINEERING GRAPH             β”‚
β”‚ Code β€’ PRs β€’ People β€’ Incidents     β”‚
β”‚ Decisions β€’ Dependencies β€’ Outcomes β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              EVIDENCE               β”‚
β”‚     GitHub β€’ CI β€’ Deployments       β”‚
β”‚      Observability β€’ Humans         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The model provides reasoning.

The tools provide action.

The graph provides memory.

Evidence provides trust.

Put those together and you get something much more interesting than an AI coding assistant.

You get an engineering system that can learn from the work it performs.

The future of AI-assisted engineering isn't just about generating code faster.

It's about building systems that understand the software they're changing.

Every commit tells a story.

Every pull request adds context.

Every incident teaches something.

Every fix creates new knowledge.

Every engineer leaves behind experience.

The opportunity is to connect all of it.

Because your code already knows what changed.

Your Git history knows when.

Your team knows why.

The problem is that nobody has connected the three.

That's what Engineering Intelligence should do.

And that's what we're building with Helix: a living engineering graph that connects software, engineering activity, decisions, and evidence so humans and AI can understand what happened before deciding what happens next.

The goal isn't AI that confidently guesses.

The goal is AI that can show its work.

Connect your GitHub and see what your code knows.

── more in #developer-tools 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/your-code-knows-what…] indexed:0 read:10min 2026-08-30 Β· β€”