VSP now has a graph-oriented analysis layer for questions that are awkward to answer with grep or a plain call graph:
- what usually changes together with this object?
- who depends on this object?
- which programs read this TVARVC variable?
This guide explains what is available today, which data sources power it, and where the current limits are.
Current graph-MVP capabilities:
- transport-based co-change analysis
- reverse dependency impact analysis
- config usage analysis for
TVARVC
Current entry points:
- CLI:
vsp graph co-change <type> <name> - CLI:
vsp graph where-used-config <variable> - MCP:
SAP(action="analyze", params={"type":"co_change", ...}) - MCP:
SAP(action="analyze", params={"type":"impact", ...}) - MCP:
SAP(action="analyze", params={"type":"where_used_config", ...})
The core implementation lives in pkg/graph.
The graph uses one canonical model:
- nodes represent ABAP objects, transport requests, or config variables
- edges point from dependent to dependency
Examples:
PROG:ZREPORT -> CALLS -> CLAS:ZCL_FOOCLAS:ZCL_FOO -> IN_TRANSPORT -> TR:A4HK900123PROG:ZREPORT -> READS_CONFIG -> TVARVC:Z_FLAG
That direction matters:
- co-change is computed from shared
IN_TRANSPORTedges - impact walks backward through
InEdges - config usage walks backward from
TVARVC:*throughREADS_CONFIG
Current MVP data sources are mixed on purpose.
Used for co-change:
E070for request/task hierarchyE071for object membership
Tasks are collapsed into parent requests during graph build, so co-change is computed at request level.
Used for code-level impact:
WBCROSSGTCROSS
These are useful as a reverse-dependency backbone, but they are still static metadata, not runtime truth.
The graph core already contains parser-based builders and query support, but the first exposed CLI/MCP slices still lean mostly on transport and SQL-backed acquisition.
Parser-based augmentation matters for cases like:
- local procedural hops
PERFORM ... IN PROGRAM ...- include-local edges that cross-reference tables do not express well
Used for TVARVC:
- variable nodes are canonical
READS_CONFIGedges are marked withSourceTVARVC_CROSS- confidence is carried in edge metadata
This is intentionally modeled as heuristic evidence, not exact repository truth.
vsp -s a4h graph co-change CLAS ZCL_PRICING
vsp -s a4h graph co-change CLAS ZCL_PRICING --top 10
vsp -s a4h graph co-change PROG ZREPORT --format json
vsp -s a4h graph co-change CLAS ZCL_PRICING --format mermaid > cochange.mmdWhat it does:
- find transports containing the target object
- resolve request/task hierarchy from
E070 - fetch sibling objects from all related request/task entries in
E071 - rank co-occurring objects by shared transport count
Good for:
- hidden change bundles
- upgrade wave planning
- spotting objects that usually move together
vsp -s a4h graph where-used-config ZKEKEKE
vsp -s a4h graph where-used-config ZKEKEKE --no-grep
vsp -s a4h graph where-used-config ZKEKEKE --format html > config.htmlWhat it does:
- queries
CROSSfor objects that reference theTVARVCtable at all - normalizes those candidates to object level
- optionally greps source for the literal variable name
- returns readers ranked by confidence
Confidence model:
HIGH= literal variable name found in sourceMEDIUM= object referencesTVARVC, but literal variable match was not confirmed or grep was skipped
SAP(action="analyze", params={
"type": "co_change",
"object_type": "CLAS",
"object_name": "ZCL_PRICING",
"top_n": 10
})SAP(action="analyze", params={
"type": "impact",
"object_type": "CLAS",
"object_name": "ZCL_FOO",
"max_depth": 3
})Parser overlay:
SAP(action="analyze", params={
"type": "impact",
"object_type": "CLAS",
"object_name": "ZCL_FOO",
"max_depth": 3,
"include_source_analysis": true
})Optional filter:
SAP(action="analyze", params={
"type": "impact",
"object_type": "CLAS",
"object_name": "ZCL_FOO",
"max_depth": 2,
"edge_kinds": "CALLS"
})SAP(action="analyze", params={
"type": "where_used_config",
"variable": "ZKEKEKE"
})Fast/noisier variant:
SAP(action="analyze", params={
"type": "where_used_config",
"variable": "ZKEKEKE",
"grep": false
})The current exposed MCP impact slice is code-level reverse dependency analysis over WBCROSSGT/CROSS, with optional parser augmentation.
It is honest, but limited:
- good for "who statically references or calls this object?"
- better with
include_source_analysis=truewhen local/procedural gaps matter - not a full runtime impact engine
- not yet the final hybrid of ADT + cross-reference tables + parser augmentation
That means:
- dynamic calls can be missed
- some include-level/procedural edge cases are improved by parser overlay, but frontier expansion still comes from
WBCROSSGT/CROSS - transport/config impact is not yet merged into the exposed
impactacquisition path
where-used-config is now wired through both CLI and MCP.
It is useful, but still intentionally heuristic:
CROSSfinds objects that touchTVARVCat all- grep upgrades confidence when the literal variable name is found
- comments/string literals can still produce false positives
- dynamic variable-name construction can still produce false negatives
Be explicit about the current boundaries:
- co-change is transport-based, not semantic similarity
- impact is static reverse dependency, not runtime trace truth
- config reads are heuristic, not exact
- no generic Cypher/Gremlin layer is exposed
- no persistence layer yet
- no auth graph yet
- Mermaid/HTML export exists for CLI co-change and where-used-config, but not for MCP or impact yet
This is deliberate. The MVP is trying to prove value first, not freeze a platform too early.
The next sensible improvements are:
- upgrade
impactacquisition further into a hybrid:WBCROSSGT/CROSSas reverse-index backbone- ADT call graph as high-confidence overlay
- parser as local/procedural gap-filler
- add export surfaces for MCP and eventually impact
- consider persistence/export once the query model settles
Use the graph features when:
- transport history matters
- reverse dependency scope matters
- grep gives too much noise
- a plain call tree is not enough
Stick to simpler tools when:
- you only need one source file
- the answer is obviously local
- runtime behavior matters more than static structure
Graph analysis is strongest when you need structure, not just text search.