Summary
Follow-up enhancements for the trace MCP tool, deferred from the v1 proposal (PR #234). These are not needed for initial implementation but should be revisited once we have production usage data.
Enhancements
1. Bidirectional traversal
The v1 trace is unidirectional ("in" or "out"), matching the neighbors contract. Some impact analysis questions benefit from mixed traversal (e.g., follow CALLS out, then INJECTS in to see what dependencies a path pulls in).
Decision for v1: Agent issues two trace calls. No "both" direction.
When to revisit: If production telemetry shows the two-call pattern is a top-3 trace usage pattern (e.g., >20% of trace calls are paired in+out on the same seed).
Open design question: A "both" direction requires specifying which edge types follow which direction — this could turn the signature into a mini query language. A simpler alternative: accept direction: list[Literal["in", "out"]] with a per-direction edge_types mapping. Needs a proposal.
2. Richer collapse_trivial heuristic
The v1 heuristic collapses chains where an intermediate node has exactly 1 in-edge and 1 out-edge in the result set, and its role is OTHER or declaring-class role is SERVICE/COMPONENT.
Decision for v1: Degree-1 heuristic, no configurability.
When to revisit: If production shows (a) false positives — collapsing chains that carry semantic meaning, or (b) false negatives — wrapper/delegate chains that don't meet the degree-1 threshold but should still collapse.
Possible v2 parameters:
trivial_chain_min_length: minimum chain length to collapse (default 2)
trivial_roles: configurable set of roles considered trivial (instead of hardcoded OTHER)
- Integration with cyclomatic complexity or method body size (if that metadata becomes available)
3. Configurable path ranking
The v1 ranking is fixed: leaf role priority > min path confidence > path length (shorter first).
Decision for v1: Fixed ranking, no rank_by parameter.
When to revisit: If agents consistently re-rank paths client-side (observable via tool call patterns — trace followed by manual filtering).
Possible v2 parameter:
rank_by: Literal["default", "shortest_first", "highest_confidence_first"] = "default"
4. Configurable fan_out_cap ranking
The v1 ranking sorts by confidence, breaks ties by role priority.
Decision for v1: Confidence primary, role tiebreaker, no parameter.
When to revisit: If production shows high-confidence but low-signal edges consistently dominate the top-K (e.g., utility/logging methods with high confidence because they're always resolved).
5. Nested tree output field
The v1 output uses a flat edges list with parent_edge_id for lightweight tree reconstruction. Each edge has a nullable parent_edge_id referencing the incoming edge to its from_id. This lets agents reconstruct the call tree without duplicating node payloads, but requires client-side processing.
A full nested tree field was proposed during review (PR #234 comment). The nested tree would give agents a ready-made hierarchical view:
"tree": {
"id": "route:com.example.orders.OrderController.createOrder",
"children": [
{
"id": "sym:com.example.orders.OrderController#createOrder",
"edge_type": "EXPOSES",
"children": [
{
"id": "sym:com.example.orders.OrderServiceImpl#createOrder",
"edge_type": "CALLS",
"children": [...]
}
]
}
]
}
Decision for v1: parent_edge_id on TraceEdge only. No nested tree.
Why deferred: The nested tree duplicates structural data already expressible from flat edges + parent_edge_id. For large traces (200+ nodes), the nested JSON adds significant token cost competing with the agent's context window — the exact problem trace exists to solve. Additionally, collapsing (collapsed: true edges with collapsed_intermediates) and cross-service boundaries (cross_service_boundary: true leaf nodes) make the tree structure more complex to consume correctly.
When to revisit: If production shows agents routinely rebuild the tree from parent_edge_id references, or if agents fail to understand call hierarchy from the flat list. This would indicate the lightweight approach is insufficient and the full tree is worth the token cost.
Possible v2 approaches:
- Add
include_tree: bool = False parameter (opt-in to avoid token cost by default)
- Compute tree from existing edges — no new traversal, just output formatting
- Tree nodes reference IDs in
nodes dict (no NodeRef duplication)
- Collapsed edges become tree nodes with
collapsed: true and children from collapsed_intermediates
- Cross-service boundary nodes become leaves with
cross_service_boundary: true
6. Cross-service: seamless multi-service traversal
The v1 cross-service design uses boundary-stop: BFS records the cross-service edge with full attributes and the downstream Route/Producer node, but does not follow into the downstream service. The agent issues a separate trace call if it wants to continue.
Decision for v1: Boundary-stop. Agent decides per-service.
When to revisit: If production shows agents always follow cross-service boundaries (every trace with cross-service edges is followed by another trace into the downstream service), seamless traversal may be worth the added complexity and context cost.
Open design questions:
- How to handle hop budget across service boundaries (scaffolding edges consume 2 hops per boundary crossing)
- How to represent multi-service paths in the
paths array (currently paths are single-service)
- How to cap total output size when traversing across 2+ services
- Whether to require explicit opt-in (
cross_service_depth: int = 0 where 0 = boundary-stop, N = follow N services deep)
Acceptance criteria
Each enhancement needs its own proposal under propose/active/ before implementation. The proposal should include production evidence justifying the change.
Dependencies
- Requires
trace v1 to be shipped and in production use
- Requires telemetry/observability on
trace usage patterns (at minimum: call counts, depth distribution, pruning stats)
Summary
Follow-up enhancements for the
traceMCP tool, deferred from the v1 proposal (PR #234). These are not needed for initial implementation but should be revisited once we have production usage data.Enhancements
1. Bidirectional traversal
The v1
traceis unidirectional ("in"or"out"), matching theneighborscontract. Some impact analysis questions benefit from mixed traversal (e.g., follow CALLS out, then INJECTS in to see what dependencies a path pulls in).Decision for v1: Agent issues two
tracecalls. No"both"direction.When to revisit: If production telemetry shows the two-call pattern is a top-3
traceusage pattern (e.g., >20% of trace calls are paired in+out on the same seed).Open design question: A
"both"direction requires specifying which edge types follow which direction — this could turn the signature into a mini query language. A simpler alternative: acceptdirection: list[Literal["in", "out"]]with a per-direction edge_types mapping. Needs a proposal.2. Richer
collapse_trivialheuristicThe v1 heuristic collapses chains where an intermediate node has exactly 1 in-edge and 1 out-edge in the result set, and its role is OTHER or declaring-class role is SERVICE/COMPONENT.
Decision for v1: Degree-1 heuristic, no configurability.
When to revisit: If production shows (a) false positives — collapsing chains that carry semantic meaning, or (b) false negatives — wrapper/delegate chains that don't meet the degree-1 threshold but should still collapse.
Possible v2 parameters:
trivial_chain_min_length: minimum chain length to collapse (default 2)trivial_roles: configurable set of roles considered trivial (instead of hardcoded OTHER)3. Configurable path ranking
The v1 ranking is fixed: leaf role priority > min path confidence > path length (shorter first).
Decision for v1: Fixed ranking, no
rank_byparameter.When to revisit: If agents consistently re-rank paths client-side (observable via tool call patterns — trace followed by manual filtering).
Possible v2 parameter:
4. Configurable fan_out_cap ranking
The v1 ranking sorts by confidence, breaks ties by role priority.
Decision for v1: Confidence primary, role tiebreaker, no parameter.
When to revisit: If production shows high-confidence but low-signal edges consistently dominate the top-K (e.g., utility/logging methods with high confidence because they're always resolved).
5. Nested
treeoutput fieldThe v1 output uses a flat
edgeslist withparent_edge_idfor lightweight tree reconstruction. Each edge has a nullableparent_edge_idreferencing the incoming edge to itsfrom_id. This lets agents reconstruct the call tree without duplicating node payloads, but requires client-side processing.A full nested
treefield was proposed during review (PR #234 comment). The nested tree would give agents a ready-made hierarchical view:Decision for v1:
parent_edge_idon TraceEdge only. No nested tree.Why deferred: The nested tree duplicates structural data already expressible from flat edges +
parent_edge_id. For large traces (200+ nodes), the nested JSON adds significant token cost competing with the agent's context window — the exact problemtraceexists to solve. Additionally, collapsing (collapsed: trueedges withcollapsed_intermediates) and cross-service boundaries (cross_service_boundary: trueleaf nodes) make the tree structure more complex to consume correctly.When to revisit: If production shows agents routinely rebuild the tree from
parent_edge_idreferences, or if agents fail to understand call hierarchy from the flat list. This would indicate the lightweight approach is insufficient and the full tree is worth the token cost.Possible v2 approaches:
include_tree: bool = Falseparameter (opt-in to avoid token cost by default)nodesdict (no NodeRef duplication)collapsed: trueand children fromcollapsed_intermediatescross_service_boundary: true6. Cross-service: seamless multi-service traversal
The v1 cross-service design uses boundary-stop: BFS records the cross-service edge with full attributes and the downstream Route/Producer node, but does not follow into the downstream service. The agent issues a separate
tracecall if it wants to continue.Decision for v1: Boundary-stop. Agent decides per-service.
When to revisit: If production shows agents always follow cross-service boundaries (every
tracewith cross-service edges is followed by anothertraceinto the downstream service), seamless traversal may be worth the added complexity and context cost.Open design questions:
pathsarray (currently paths are single-service)cross_service_depth: int = 0where 0 = boundary-stop, N = follow N services deep)Acceptance criteria
Each enhancement needs its own proposal under
propose/active/before implementation. The proposal should include production evidence justifying the change.Dependencies
tracev1 to be shipped and in production usetraceusage patterns (at minimum: call counts, depth distribution, pruning stats)