@@ -165,9 +165,6 @@ $ canpy --help
165165│ --emit schema). │
166166│ --output -o <path> Output directory for │
167167│ artifacts. │
168- │ --format -f <json> Output format for --emit │
169- │ json: json. │
170- │ [default: json] │
171168│ --emit <json|neo4j|schema> Output target: json │
172169│ (analysis.json, default) | │
173170│ neo4j (graph.cypher or live │
@@ -273,13 +270,14 @@ $ canpy --help
273270 canpy --input ./my-python-project --output ./out --format msgpack # → ./out/analysis.msgpack
274271 ```
275272
276- 3 . ** Enrich the call graph with PyCG (level 2):**
273+ 3 . ** Enrich the call graph with the defuse linker (level 2):**
277274 ``` sh
278275 canpy --input ./my-python-project -a 2
279276 ```
280- Level 1 edges come from Jedi's lexical resolution. ` -a 2 ` runs ** PyCG** and merges its
281- flow-sensitive edges in (RPC / third-party / dynamically-dispatched targets), backfilling
282- callees Jedi could not resolve. Every edge is provenance-tagged (e.g. ` jedi ` , ` pycg ` ).
277+ Level 1 edges come from Jedi's lexical resolution. ` -a 2 ` runs the ** defuse linker** —
278+ per-callable resolution over lexical scopes, import bindings, class hierarchies, and a
279+ bounded type-propagation round — and merges its edges with Jedi's, backfilling the
280+ callees Jedi could not resolve. Every edge is provenance-tagged (` jedi ` , ` defuse ` ).
283281
2842824 . ** Emit a Neo4j snapshot, or push to a live database:**
285283 ``` sh
@@ -321,7 +319,7 @@ levels are cumulative and additive — `analysis.json(-a 1) ⊆ … ⊆ analysis
321319| Level | Flag | What it adds | Where it lands |
322320| --- | --- | --- | --- |
323321| ** 1** | ` -a 1 ` (default) | Symbol table, Jedi call graph, and ` call ` nodes in each callable's ` body ` | ` body ` calls (` callee: null ` ) |
324- | ** 2** | ` -a 2 ` | PyCG call-graph enrichment; each call's ` callee ` backfilled to a ` can:// ` id | ` call_graph ` , ` body ` callees |
322+ | ** 2** | ` -a 2 ` | Defuse-linker call-graph enrichment; each call's ` callee ` backfilled to a ` can:// ` id | ` call_graph ` , ` body ` callees |
325323| ** 3** | ` -a 3 ` | Native ** intraprocedural** CFG/CDG/DDG (syntactic, name-equality, ` prov: ["ssa"] ` ) | ` cfg ` , ` cdg ` , ` ddg ` , ` @entry ` /` @exit ` on each callable |
326324| ** 4** | ` -a 4 ` | ** Interprocedural** SDG: synthetic param vertices, alias-aware DDG (` prov: ["points-to"] ` ) | ` param_in ` , ` param_out ` , ` summary ` , semantic ` ddg ` |
327325
@@ -350,7 +348,7 @@ symbol-table signature by construction
350348 external dependency to install; the analyzer falls back to the built-in ` TypeBasedAliasOracle `
351349 (Jedi-inferred types; unknown types conservatively alias) only when Scalpel can't resolve a
352350 construct or a per-callable build fails, keeping the ` may_alias ` interface total. Call dispatch
353- comes from the merged Jedi(+PyCG) call graph, treated as a frozen oracle.
351+ comes from the merged Jedi + defuse-linker call graph, treated as a frozen oracle.
354352- ** Summaries:** relational formal-in → formal-out flows composed bottom-up over the Tarjan SCC
355353 condensation of the call graph, a monotone fixpoint within SCCs; globals ride as extra formals,
356354 closure captures bind at definition sites.
@@ -389,7 +387,7 @@ just populate more of the same tree:
389387 }
390388 },
391389 " call_graph" : [ { " src" : " can://…/main(a)" , " dst" : " can://…/helper(x)" ,
392- " weight" : 1 , " prov" : [" jedi " , " pycg " ] } ],
390+ " weight" : 1 , " prov" : [" defuse " , " jedi " ] } ],
393391 " external_symbols" : { // imported/builtin call targets, keyed by id
394392 " can://python/<app>/@external/os/getcwd" :
395393 { " id" : " can://python/<app>/@external/os/getcwd" , " kind" : " external" ,
0 commit comments