Problem
Some Go packages in a monorepo serve as both a reusable library and a deployable service. For example, in eigenda:
node/ exports reusable types and functions consumed by other packages (library)
node/cmd/ has a main.go that runs the node as a long-running process (service)
The current discovery engine handles this by splitting into two separate components (node as library, node-cmd as service). The LLM-generated artifacts handled it by classifying the whole thing as a single application. Neither is fully correct:
- Splitting loses the semantic connection — consumers need to know that the library and the service are the same logical unit.
- Merging loses precision — you can't distinguish "I depend on node's exported API" from "I interact with node's running process over gRPC."
This pattern is common across eigenda (node, relay, retriever, ejector all exhibit it) and likely across other Go monorepos.
Proposed approach
Allow a component to hold multiple ComponentKind values rather than exactly one:
# Current
kind: ComponentKind # single value
# Proposed
kinds: Set[ComponentKind] # e.g., {LIBRARY, SERVICE}
Or alternatively, model it as a single logical component with sub-roles:
class Component:
name: str
kind: ComponentKind # primary classification
sub_components: list[SubComponent] # e.g., cmd/ entrypoint
class SubComponent:
name: str
kind: ComponentKind # e.g., SERVICE
root_path: str # e.g., node/cmd
entrypoint: str # e.g., main.go
This would let the graph represent node as a single node with both library and service roles. Consumers that import node packages get a library edge; components that communicate with the running node process get a service interaction edge.
Affected areas
agent/schemas/core.py — Component and ComponentKind
agent/discovery/languages/go.py — classification logic that currently splits into two components
agent/utils/dependency_graph.py — graph edges may need to distinguish "imports" from "communicates with"
- Analysis templates — a dual-classified component needs sections from both the library and service templates
- Universal graph — node rendering for dual-role components
Problem
Some Go packages in a monorepo serve as both a reusable library and a deployable service. For example, in eigenda:
node/exports reusable types and functions consumed by other packages (library)node/cmd/has amain.gothat runs the node as a long-running process (service)The current discovery engine handles this by splitting into two separate components (
nodeas library,node-cmdas service). The LLM-generated artifacts handled it by classifying the whole thing as a singleapplication. Neither is fully correct:This pattern is common across eigenda (
node,relay,retriever,ejectorall exhibit it) and likely across other Go monorepos.Proposed approach
Allow a component to hold multiple
ComponentKindvalues rather than exactly one:Or alternatively, model it as a single logical component with sub-roles:
This would let the graph represent
nodeas a single node with both library and service roles. Consumers that importnodepackages get a library edge; components that communicate with the running node process get a service interaction edge.Affected areas
agent/schemas/core.py—ComponentandComponentKindagent/discovery/languages/go.py— classification logic that currently splits into two componentsagent/utils/dependency_graph.py— graph edges may need to distinguish "imports" from "communicates with"