Show me the structure — dependencies, data flow, entry points and business flows, as an interactive map
复制下面这句话,粘贴给 Claude Code、Codex、Cursor 等 AI 编程工具,它会读取安装说明并在你确认后完成安装。
请阅读 https://ai.atlankj.com/install/asset/gh-claude-plugins-official-dace88cb3d6a ,按照其中的说明把「modernize-map」安装到你(当前 AI 工具)中。执行前先告诉我将运行的命令和写入的位置,等我确认。
查看 AI 将读取的安装说明正在读取 GitHub 原文…
内容来自 GitHub 原始文件,由原作者维护。在 GitHub 查看
Build a dependency and topology map of the system and render it as an interactive page. The assessment found the domains; this goes one level down: how do the pieces connect? It is the map an engineer needs before touching anything.
The code is legacy/$system, often a symlink to where it really lives: say where it points (readlink legacy/$system) in one line before you start. If legacy/$system does not exist, stop and say so: nothing can run without the code, so the fix is /code-modernization:modernize $system --source <path to the code>. Run every subagent in the foreground and wait for its result: never end your turn while one is still running.
Do not reinvent a dependency graph the customer or the ecosystem already has:
--graph <file> — if $ARGUMENTS names an existing dependency export (a
compiler index, an MSBuild or Roslyn graph, an NDepend or jdeps export, a call
graph in JSON, CSV, DOT or GraphML), read it and map its nodes and edges into
topology.json instead of writing a parsing script. Spot-check about ten edges
against the source, say what the file did not cover, and still add what graphs
omit: entry points from deployment config, data stores, business flows.legacy/$system and read its
machine-readable output (JSON, DOT, XML), never pretty-printed text: jdeps or
the Maven/Gradle dependency reports for Java, the project graph for .NET,
madge or dependency-cruiser for JavaScript, pydeps for Python,
go list -deps, cargo metadata. Use it for the module and import graph; your
script adds the config-driven edges, entry points and data joins tools miss.Big estates (more than about 2,000 source files or 500k lines) are mapped in
chunks, not in one pass: one domain or top-level directory at a time, each writing
analysis/$system/map/<chunk>.json (its modules and the edges it originates). A
rerun skips chunks whose file exists, so an interrupted map resumes. When all exist,
merge them into topology.json; an edge into another chunk resolves by id, and an
unresolved one becomes an observation. Say which chunks ran and which are missing.
Write a one-off script (Python or shell) that parses legacy/$system and extracts the
datasets below. Three principles matter across stacks:
CALL, method invocations, import/require) and
dispatcher calls (EXEC CICS LINK/XCTL, DI wiring, framework routing, factories).SELECT…ASSIGN with JCL DD, CICS file with CSD DEFINE FILE,
EXEC SQL tables, ORM mappings, model files). Screens, JSPs and templates too.EXEC PGM= and CSD
transactions, web.xml or route files, main(), queue and scheduler subscriptions.For fixed-column source (COBOL columns 8–72, RPG), slice the code area and strip comment lines before matching, or you will match sequence numbers.
Save the script as analysis/$system/extract_topology.py (or .sh) so it can be
rerun and audited. It writes analysis/$system/topology.json and prints a summary
(cap at ~200 lines for large estates). Run it and show the summary.
topology.json feeds the viewer and must follow this schema:
{
"system": "<display name>",
"root": {
"id": "sys", "name": "<system>", "kind": "system",
"children": [
{ "id": "dom:<domain>", "name": "<Domain>", "kind": "domain",
"children": [
{ "id": "<MODULE>", "name": "<MODULE>", "kind": "module",
"language": "cobol", "loc": 1234, "file": "src/MODULE.cbl" }
] },
{ "id": "dom:data", "name": "Data stores", "kind": "domain",
"children": [ { "id": "ds:<NAME>", "name": "<NAME>", "kind": "datastore" } ] }
]
},
"edges": [ { "source": "<id>", "target": "<id>", "kind": "call" } ],
"entryPoints": ["<id>"],
"deadEnds": ["<id>"],
"observations": ["<architect observation>"],
"flows": [
{ "name": "<business flow>", "persona": "<who experiences it>",
"description": "<one sentence, plain language>",
"steps": [ { "label": "<business-language step>", "nodes": ["<id>", "<id>"] } ] }
]
}
domain containers (the domains from assess, if it
ran). Leaf kinds: module, datastore, job, screen. loc sizes the circle.file is its own source file. For a build module or package made of many files, give
its own directory, and never give two leaves the same location (a node per sub-package points
at that sub-package's directory, not at the module's): extract-rules shards by these locations.call, dispatch (dynamic or router), read, write. Every edge
endpoint must be a leaf id in the tree.deadEnds render dashed; apply the suppression rule above.observations.observations: 3–7 architect observations: coupling clusters, single points of
failure, extraction candidates, stores with too many writers, dynamic targets left
unresolved.description (optional, leaf nodes) is filled by "Describe each node" below.Trace 2–4 end-to-end business flows, each anchored to a persona who experiences
the system, not one who maintains it (for benefits: the claimant, the caseworker,
the auditor). Each has a name and one-sentence description a steering-committee
member relates to ("a claimant files a weekly claim"), and 3–8 steps, each with a
business-language label and the nodes that implement it, in execution order.
Unless $ARGUMENTS contains --no-describe, give leaf nodes a description: one
paragraph of 55 to 90 words: what the node does in business terms, then what it
calls, reads, writes or is called by. The viewer shows it in the sidebar.
loc (the default), or none. With no pop-up available (a headless
run) do the 40 largest. Say how many agents will run.topology.json. Check that every number and identifier-like name in a paragraph
occurs in its packet, re-ask once for any that fails, then leave that node
without a description.extract_topology.py.analysis/$system/TOPOLOGY.html is an interactive map: a zoomable circle-pack (domains
as containers, modules sized by LOC), dependency edges, search, a per-node sidebar,
edge-kind toggles, and a walkthrough that plays each persona flow. Build it from the
template this plugin ships; do not hand-write a viewer:
python3 - "${CLAUDE_PLUGIN_ROOT}/assets/topology-viewer.html" analysis/$system <<'EOF'
import json, sys
tpl_path, out_dir = sys.argv[1], sys.argv[2]
tpl = open(tpl_path).read()
marker = "/*__TOPOLOGY_DATA__*/ null"
assert marker in tpl, f"injection marker not found in {tpl_path}"
data = json.dumps(json.load(open(f"{out_dir}/topology.json")))
# topology.json comes from UNTRUSTED source (names from filenames, observations from
# analyzed code). The data lands in a <script> block, which the HTML parser closes on
# the literal bytes "</script>" whatever the JS string context, and json.dumps does not
# escape "<". Escape it to kill the breakout.
data = data.replace("<", "\\u003c").replace(">", "\\u003e").replace("&", "\\u0026")
open(f"{out_dir}/TOPOLOGY.html", "w").write(tpl.replace(marker, "/*__TOPOLOGY_DATA__*/ " + data))
print(f"wrote {out_dir}/TOPOLOGY.html")
EOF
The viewer is self-contained (the d3 subset it needs is inlined), so it works offline.
If the template is not found, ${CLAUDE_PLUGIN_ROOT} was not substituted: report
that rather than hand-writing a viewer.
Also write small, exportable Mermaid files (each under ~40 edges; collapse to domain
level if the graph is bigger, since dense Mermaid is unreadable): call-graph.mmd
(domain-level graph TD, entry points highlighted), data-lineage.mmd (graph LR,
programs to stores, read versus write marked), critical-path.mmd (flowchart TD of
the primary flow, with p50/p99 if assess gathered telemetry), all in
analysis/$system/.
Refresh the report: python3 "${CLAUDE_PLUGIN_ROOT}/scripts/build_report.py" $system
(a convenience: if it fails or python3 is missing, say so in one line and carry on). Tell the user to open
analysis/$system/TOPOLOGY.html and try: search a module, click it for its
connections and description, pick a persona flow. The next step is
/code-modernization:modernize-extract-rules $system.