KognitaKognita.

Blog

Code Indexing Captures Your Source. It Misses What Your System Actually Does.

10 min read

Every AI coding tool indexes source files. Cursor embeds them, Copilot retrieves from them, Claude Code reads them into context. What none of them can index is what your code actually does when it runs in production — the environment variables that route traffic differently, the feature flags that activate alternate code paths, the infrastructure that transforms a function call into a distributed system interaction. Code indexing captures what you wrote. It has no access to what happens when you deploy it.

What code indexing captures and what it misses

Semantic code indexing — whether from Cursor, Copilot, or any similar tool — reads static source files. The embeddings it generates represent the text of your code: function names, class hierarchies, import graphs, comment strings. This is genuinely useful for navigation and retrieval. But it is a snapshot of your source, not a representation of your running system:

The gap between code indexing and runtime reality
What code indexing captures:
  ✓ Function signatures and method names
  ✓ Class hierarchies and import graphs
  ✓ Variable names and inline comments
  ✓ Directory structure and file organization
  ✓ Syntactic patterns and code style

What code indexing misses:
  ✗ Runtime execution paths (which code actually runs in production)
  ✗ Environment-specific behavior (staging vs. prod configs)
  ✗ Database state and schema at runtime
  ✗ Infrastructure topology (which services talk to which)
  ✗ Async side effects and queue consumers
  ✗ Feature flag states and their effect on code paths
  ✗ External API behavior and contract drift

This gap does not matter for simple questions. "Where is the login function?" — the index answers this well. It starts mattering the moment the question is "why does login behave differently for enterprise customers?" — which requires understanding feature flags, environment configs, and database state that the index cannot see.

Payment processing: the gap in concrete terms

Consider a payment processing service. The code index sees the function names and call graph. The runtime behavior is driven by environment configuration, feature flags, and infrastructure state that exist entirely outside the source files:

What indexing sees vs. what runs in production
Payment processing code (what the index sees):
  → processPayment(amount, customerId)
  → chargeCard(cardToken, amount)
  → recordTransaction(txId, status)

Payment processing at runtime (what the index misses):
  → feature flag: new_payment_provider=true for 10% of users
  → ENV=production → routes to Stripe, not Braintree
  → database connection pool exhaustion → falls back to queue
  → idempotency key check → skips duplicate charges silently
  → audit logging → writes to separate compliance DB

When a developer asks "why is the payment failing for this specific user?" — the relevant answer is in the feature flag state, the connection pool status, and the idempotency check behavior. None of that is in the source code index. This is exactly the problem class that incident response context lives nowhere describes.

Environment-specific behavior invisible to static indexing

Modern software systems behave differently by environment. The same codebase that runs harmlessly in development routes production traffic through real payment processors, external APIs, and live databases. Code indexing cannot distinguish between these environments because it indexes the source, not the configuration:

Same code, radically different behavior by environment
Feature behavior that changes by environment:
  development:  mock payment processor, no email sends
  staging:      real processor, emails go to test inbox
  production:   real processor + Stripe webhooks + Braintree fallback

Code indexing sees the same source in all three.
Runtime behavior is completely different.

When an AI coding tool suggests "just add an email send here," it does not know that in the production environment, email sends go through a rate-limited SES queue with a compliance-mandated audit trail. The code to call sendEmail() looks the same in every environment. What it does in production is a different story entirely.

Infrastructure topology is invisible to code indexing

"What does this service depend on?" is one of the most common questions in debugging and impact analysis. Code indexing gives you the import graph — which packages a service imports. Runtime topology is typically determined by environment configuration, infrastructure-as-code, and service mesh settings that live outside source files and change independently:

Infrastructure dependencies invisible to code indexing
"What does the notification service depend on?"

Code index answer:
  → imports: axios, nodemailer, pg, redis
  → calls: sendEmail(), pushNotification(), logEvent()

Runtime reality:
  → SES for transactional email (configured via ENV)
  → SNS topic for push (ARN in secrets manager)
  → Aurora RDS for writes (DNS resolved at runtime)
  → ElastiCache for rate limiting (injected by ECS task role)
  → Kinesis stream for event logging (configured in K8s ConfigMap)

This is why AI coding tools tend to be useful for local function-level questions and unreliable for system-level questions. The function is in the source file. The system is in the infrastructure. This is the architectural gap described in codebases as graphs of logical units.

Why this matters for debugging and refactoring

The practical consequence is that AI coding tools are most helpful at the moments they are least needed: simple navigation, function-level autocomplete, local refactoring. They underperform exactly when you most need them: a production bug with unclear symptoms, a refactoring with unknown downstream effects, a service change that might break something you cannot see from within the repo.

In all three cases, the relevant context is runtime behavior, not source structure. And runtime behavior is the one thing code indexing cannot capture.

How Kognita approaches the gap

Kognita's semantic layer indexes more than source files. The enrichment pipeline reconstructs behavioral relationships — which services communicate, what events flow between them, what data patterns indicate ownership and dependency. The index is still built from source, but it is augmented with structural analysis that reconstructs operational topology rather than just syntactic relationships.

This does not fully solve the runtime gap — true runtime state requires observability tooling, not indexing. But it substantially narrows it by reconstructing behavioral intent from code structure rather than just finding similar-looking code. The difference is between "these chunks look related" and "this service owns this flow."

Final take

Code indexing answers questions about what you wrote. Runtime behavior is determined by what you deployed, how you configured it, and what your infrastructure does to it in transit. These are different things, and the gap between them is where most serious bugs live.

AI coding tools will continue improving at static code retrieval. But the hardest questions in software engineering are not answered in the source files. Closing the gap between indexed code and running system requires a semantic layer that understands operational relationships, not just syntactic similarity.