🕵️ SicherheitslückenWhat continuous operational resilience looks like under DORA(09.09.2026 um 17:53 Uhr)
🔧 AI Nachrichten OpenAI seeks tougher AI rules. CIOs may feel the ripple effects(10.09.2026 um 12:11 Uhr)
🔧 AI Nachrichten Mistral valued at €21bn after €3bn Series D funding round(08.09.2026 um 10:19 Uhr)
🪟 Windows TippsWindows XP's Cursor Indicator Is Getting a Windows 11 Refresh(25.08.2026 um 13:00 Uhr)
🕵️ SicherheitslückenWhat continuous operational resilience looks like under DORA(09.09.2026 um 17:53 Uhr)
🔧 AI Nachrichten OpenAI seeks tougher AI rules. CIOs may feel the ripple effects(10.09.2026 um 12:11 Uhr)
🔧 AI Nachrichten Mistral valued at €21bn after €3bn Series D funding round(08.09.2026 um 10:19 Uhr)
🪟 Windows TippsWindows XP's Cursor Indicator Is Getting a Windows 11 Refresh(25.08.2026 um 13:00 Uhr)

🔧 Programmierung 🕛 vor 1 Monat 6 Min Lesezeit
0

Building Enola, Part 2: From Source Code to an Architectural Fact Model

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

In Part 1, I explained why Enola extracts deterministic architectural facts before an AI agent begins reasoning.



That leaves the next design question:



How should those facts be represented?



The obvious answer is to build a graph containing every symbol, dependency, route, service, and repository.



But the difficult part is not putting nodes and edges into a graph.



It is preserving what those relationships mean.



A function call is not the same as a package dependency. A route registration is not an import. A type reference is not proof that two services share a contract.



If every relationship becomes a generic connection, the resulting graph may be traversable, but it is no longer reliable enough for architectural analysis.



Enola therefore begins with a typed architectural fact model.






Parsing gives us evidence, not architecture



A parser can tell us that a function call, string literal, import, annotation, or method declaration exists.



That is necessary, but it is not yet an architectural fact.



Consider a Go application:




CODE
api := router.PathPrefix("/api").Subrouter()
registerCourseRoutes(api)






Elsewhere:




CODE
func registerCourseRoutes(router *mux.Router) {
router.HandleFunc("/courses", listCourses)
}






The parser can expose both string literals and both function calls.



The architectural fact is:




CODE
GET /api/courses
-> handled_by listCourses






Producing that fact requires understanding the framework, how routers compose paths, and how values move through function calls.



The same problem appears in Spring annotations, Rails scopes, Axum routers, Next.js file conventions, generated clients, dependency-injection frameworks, and message-bus configuration.



Enola therefore separates parsing from architectural extraction:




CODE
Source code

Language and framework interpretation

Architectural facts






The parser provides syntax.



The extractor determines what the syntax means within the architecture.






Repository boundaries are extraction scopes



A Git repository is a convenient place to begin analysis.



It provides a source revision, configuration boundary, files, build metadata, and stable source locations.



But it is not necessarily a unit of architectural truth.



A monorepo may contain several independently deployed services. A small repository may depend on schemas, infrastructure, or generated clients maintained elsewhere. Runtime behavior may also depend on deployment configuration outside the application repository.



Enola therefore treats a repository as an independently addressable extraction scope.



Within that scope, Enola may establish facts such as:




CODE
Repository contains module
Module contains file
File declares symbol
Function calls function
Package imports package
Type implements interface
Route is handled by symbol
Producer publishes to topic






These facts remain useful even when no other repositories are loaded.



The scope gives each entity a local identity and provenance. It does not imply that the entire architecture is contained inside the repository.



That distinction matters because source ownership boundaries and architectural boundaries are rarely identical.






Different facts require different identity rules



There is no universal identifier that works for every architectural concept.



A symbol may require:




  • extraction scope;

  • language;

  • qualified name;

  • source location;

  • source revision.



An HTTP route may require:




  • method;

  • normalized path;

  • service context.



A gRPC method may require:




  • package;

  • service;

  • method.



A Kafka topic may require:




  • resolved topic name;

  • namespace or environment context.



This is why names alone are insufficient.



Two repositories may both contain UserDTO without referring to the same contract. Conversely, a Go type called PublicUser and a Swift type called ProfileResponse may represent two sides of the same API.



Enola keeps those entities separate until there is evidence establishing a relationship between them.






Typed relationships preserve the reason two things are connected



A generic graph might represent:




CODE
A -> B






But architectural analysis needs to know why that edge exists.



Compare:




CODE
CheckoutController
-> calls PaymentService.authorize









CODE
checkout
-> imports payments









CODE
POST /checkout
-> handled_by CheckoutController






These relationships support different questions.



A call edge may be useful for reachability.



An import edge may be useful for dependency-cycle detection.



A route-to-handler edge may be useful for tracing request execution.



Direction matters as well. A client consumes a route. The route does not consume the client.



Enola therefore represents relationships as typed and directed facts rather than generic connectivity.



That still does not make every extracted edge equally strong.



A relationship should also retain the evidence used to produce it, including:




  • source locations;

  • extractor;

  • resolution method;

  • source revision;

  • configuration;

  • whether it was directly extracted or derived.



Without that evidence, the graph becomes another opaque answer.






One model, several analysis projections



The complete fact model contains more relationships than any single analysis should traverse.



The question determines which subset is relevant.



For package-cycle detection:




CODE
Nodes: packages
Edges: package dependencies






For symbol reachability:




CODE
Nodes: symbols
Edges: calls and references






For route execution:




CODE
Nodes: routes, handlers, services
Edges: handled_by and calls






This matters because using every available edge can produce technically connected but architecturally meaningless paths.



Suppose a type belongs to a package, that package depends on another package, and the second package contains an HTTP route.



There is a path through the full graph.



That does not mean the type participates in the route’s execution.



Enola therefore constructs constrained projections for specific analyses instead of treating every traversal as equivalent.






A concrete example: why a generic dependency graph fails



Consider a frontend and backend stored in the same monorepo.



The frontend imports an API client package:




CODE
web
-> depends_on api-client






The backend imports a routing framework:




CODE
backend
-> depends_on router






A conventional dependency graph correctly records both relationships.



But it cannot answer:




Which frontend method consumes POST /api/orders?




The answer requires several additional facts:




CODE
submitOrder
-> makes_request POST /api/orders









CODE
POST /api/orders
-> handled_by CreateOrderHandler









CODE
CreateOrderHandler
-> calls OrderService.Create






The useful architectural path is not a package-dependency path.



It is a projection combining request, route, handler, and call relationships.



That is the reason Enola needs a typed architectural fact model rather than only a repository dependency graph.






The limit of the model



Enola constructs the architecture that can be established from the loaded source and configuration inputs.



It does not claim that source alone describes every aspect of a production system.



Deployment manifests, gateways, service meshes, runtime configuration, reflection, feature flags, and infrastructure may alter the architecture visible at runtime.



The model should therefore distinguish between:




  • established facts;

  • derived relationships;

  • unresolved relationships;

  • information outside the analyzed scope.



This is important for both developers and agents.



A missing edge does not always mean that no relationship exists. It may mean that the relevant source, configuration, or resolver was unavailable.






What comes next



A typed fact model can explain the architecture inside one extraction scope.



Production systems cross those scopes.



A mobile client calls a backend maintained elsewhere. A service publishes an event consumed by another repository. A generated client implements a contract defined in a separate codebase.



The next post will explain how Enola connects these independently extracted models without merging entities based on names or similarity alone.



Enola is open-source GitHub

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Sam Altman calls GPT-6 Astra rollout ‘messy’ as enterprise users wait for access
1 Quelle
Swiss government explores replacing Microsoft 365 with open-source software
1 Quelle
What continuous operational resilience looks like under DORA