@@ -5,6 +5,143 @@ All notable changes to this project will be documented in this file.
55The format is based on [ Keep a Changelog] ( https://keepachangelog.com/en/1.0.0/ ) ,
66and this project adheres to [ Semantic Versioning] ( https://semver.org/spec/v2.0.0.html ) .
77
8+ ## [ v2.0.0] - 2026-10-15
9+
10+ CLDK 2.0 gives Python, Java and TypeScript one agent-facing query surface — addressing, per-callable
11+ control and data flow, slices, call-graph and value-flow predicates, entrypoints and the
12+ repository-artifact layer — answered identically from an ` analysis.json ` or an attached Neo4j graph.
13+ No code changes since ` v2.0.0-rc.8 ` except the README split into a user page, ` docs/architecture.md `
14+ and ` docs/citations.md ` (#416 ). The rc sections below are the full record; this section lists what
15+ breaks for code written against ** 1.5.0** , each with its migration step.
16+
17+ ### Breaking (since 1.5.0)
18+
19+ - ** C support is removed** (` CLDK.c() ` , ` cldk.analysis.c ` , ` cldk.models.c ` ; rc.2). There is no
20+ replacement; pin ` cldk<2 ` if you need it.
21+ - ** Java needs the ` java ` extra.** The analyzer ships as the ` codeanalyzer-java ` wheel with its own
22+ JVM, not a jar in this repo (rc.3). Install with ` pip install "cldk[java]" ` .
23+ - ** Every Neo4j graph must be re-emitted, into a wiped database.** The ` can:// ` id grammar now puts the
24+ application outermost (` can://<app>/<lang>/... ` , rc.4), and each backend refuses a graph below its
25+ floor at attach with ` GraphSchemaMismatch ` , rather than answering with zero rows. The floors are
26+ ` codeanalyzer-python ` 1.5.0, ` codeanalyzer-typescript ` 1.5.2 and ` codeanalyzer-java ` 3.2.0 (rc.6).
27+ Re-emit with the pinned analyzer (` --emit neo4j ` ); there is no in-place upgrade.
28+ - ** Java and TypeScript models mirror schema v2** (rc.3). A 1.x ` analysis.json ` is refused rather than
29+ parsed: re-run the analysis with the pinned analyzer. For Java, ` get_call_graph() ` nodes are
30+ ` "<type fqn>.<signature>" ` strings rather than ` (signature, klass) ` tuples — read the class from
31+ ` cg.nodes[key]["method_detail"].klass ` . Local and anonymous class names carry their declaring callable
32+ — take class keys from ` get_all_classes() ` rather than composing them. ` JGraphEdges ` is
33+ ` {src, dst, prov, weight} ` . For TypeScript, ` TSCallable ` and ` TSModule ` lost their per-file fields (v2
34+ keys modules by path).
35+ - ** Java's single-file ` source_code ` mode is gone** (rc.3). Analyze the project directory.
36+ - ** ` PyCallableOverview.path ` is repo-relative** , not an absolute path (rc.2). Stop stripping a
37+ project-root prefix off it.
38+ - ** Accessors that only ever raised ` NotImplementedError ` are removed** : fifteen on ` PythonAnalysis `
39+ (rc.2) and ` get_entry_point_methods ` / ` get_service_entry_point_methods ` on ` TypeScriptAnalysis `
40+ (rc.3). Use ` get_entrypoints() ` / ` get_entrypoint_classes() ` .
41+
42+ ### Analyzer pins
43+
44+ ` codeanalyzer-python==1.5.3 ` , ` codeanalyzer-typescript==1.6.0 ` , ` codeanalyzer-java==3.3.3 ` (extra).
45+
46+ ## [ v2.0.0-rc.8] - 2026-09-16
47+
48+ ### Fixed
49+
50+ - ** ` locate ` places a position on a decorator line on the decorated callable, on both Python
51+ backends** (` python-sdk#408 ` ). ` PyCallable.start_line ` is the ` def ` line (` ast.FunctionDef.lineno ` )
52+ and Python's AST puts decorators above it, so ` @http.route(...) ` sat inside no callable span and
53+ came back as ` module_scope ` . Both backends now read where the decorator is * applied* :
54+ ` _find_innermost ` admits the callable whose ` decorators[].span ` starts at or before the line and
55+ above its ` def ` ; ` _LOCATE_QUERY ` gains one ` EXISTS ` disjunct over ` PY_DECORATED_BY.start_line ` ,
56+ which codeanalyzer-python 1.5.2 emits. Ranking is unchanged (the def-based width), so a decorator
57+ on a nested callable resolves to the nested one. Three things deliberately stay as they were: a
58+ position between two callables with no decorator over it is still ` module_scope ` (this is not a
59+ nearest-callable fallback); a ** class** decorator is still ` module_scope ` (a result with ` type `
60+ set and ` callable ` unset is a new shape and needs its own decision); and an analysis or graph from
61+ codeanalyzer-python 1.5.1 or earlier, which records no decorator span, answers exactly as before.
62+ Measured on odoo-slim-19 re-emitted by 1.5.3, 40 positions, median of 5, same graph both ways:
63+ 71.0 ms placing 20/40 → 70.2 ms placing 40/40; the plan still seeks ` pysymbol_id ` .
64+
65+ ### Changed
66+
67+ - ` codeanalyzer-python ` pin ` 1.5.2 ` → ** ` 1.5.3 ` ** (` dependencies ` and ` [tool.backend-versions] ` ,
68+ ` python-sdk#410 ` ). Two analyzer fixes, neither moving the schema (` schema_version ` and the graph
69+ ` SCHEMA_VERSION ` stay ` 2.0.0 ` ; ` PyNeo4jBackend._ANALYZER_FLOOR ` stays ` 1.5.0 ` ):
70+ - the analyzer no longer ingests its own output (codeanalyzer-python #207 ). ` discover_artifacts `
71+ had no idea where the run writes, so an output or cache directory inside the input made run N
72+ inventory run N-1's ` analysis.json ` and embed it whole. This SDK's default ` cache_dir ` is
73+ ` <project>/.codeanalyzer ` , inside the input, so every local run was exposed.
74+ - one body node per call site when two calls share a start position (codeanalyzer-python #215 ).
75+ ` getattr(o, n)(x) ` starts the outer application and the inner ` getattr ` at the same column, and
76+ the position-keyed ` body ` kept the inner one. Keys now carry a ` /2 ` , ` /3 ` disambiguator,
77+ outermost first; ` body_key_column ` already splits on ` / ` and needed no change. A key that used
78+ to collide now names the ** outer** call, and a call whose callee is itself a call carries
79+ ` callee_signature: null ` with ` method_name: "<unknown>" ` .
80+
81+ ### Verification
82+
83+ The Python tier offline (` tests/analysis/python ` , mocked Neo4j and the in-process analyzer):
84+ 482 passed, 168 skipped, on 1.5.2 and on 1.5.3 alike — every skip is a live-Neo4j tier. No fixture
85+ expectation moved.
86+
87+ ## [ v2.0.0-rc.7] - 2026-09-11
88+
89+ The Java facade learns the view layer codeanalyzer-java 3.3.0–3.3.2 added, and the 2.0 line takes up
90+ everything rc.6 shipped from ` main ` (the 3.2.0 text model and the sibling-analyzer pins) — this is
91+ the first release cut from ` release/2.0 ` that contains rc.6.
92+
93+ ### Added
94+
95+ ** Java view dispatches** (` python-sdk#404 ` , spec ` codellm-devkit/.github `
96+ ` docs/design/specs/2026-09-11-java-view-templates-and-dispatch.md ` ). JSP, Facelets and Thymeleaf
97+ templates are artifacts with ` roles: ["view-template"] ` , and the analyzer now says which code reaches
98+ one. Three accessors on ` JavaAnalysis ` , both backends:
99+
100+ - ` get_view_dispatches(view=None) -> List[JViewDispatch] ` — every resolved dispatch: the body node
101+ that hands the request over (a ` forward ` / ` include ` / ` sendRedirect ` call, a ` ModelAndView `
102+ construction or ` setViewName ` , or a Spring controller's ` return ` ) and the artifact it reaches,
103+ with ` via ` naming the mechanism and ` prov ` the tier. ` literal ` and ` dataflow ` mean exactly one
104+ target; ` table ` (3.3.1) is a may-dispatch over a static string table, one edge per entry, from
105+ the same site. ` view ` filters by a segment-aligned suffix of the artifact's path.
106+ - ` get_view_dispatchers(path) -> List[JCallableOverview] ` — the same edges resolved to the callables
107+ that own the dispatching sites.
108+ - ` get_unresolved_view_dispatches() -> List[JViewDispatchUnresolved] ` — what closed on nothing (a
109+ variable target, a servlet URL, a view name matching two templates), with its reason and the tiers
110+ attempted. JSON-only: the graph has no node for a target that resolved to nothing, so the Neo4j
111+ backend refuses this one rather than answering ` [] ` .
112+
113+ Two models, ` JViewDispatch ` and ` JViewDispatchUnresolved ` , on ` JApplication.view_dispatches ` /
114+ ` .view_dispatches_unresolved ` ; the Neo4j backend reads ` J_DISPATCHES_TO ` back into the former.
115+
116+ One rule stated because it is the only one of its kind: ** this layer is gated on the analyzer
117+ generation.** The 3.1.0 config trio is probed by an always-present sibling key; 3.3.x added none —
118+ both lists are written only when non-empty and the edge type is declared only once an edge exists —
119+ so a pre-3.3.0 analysis is refused from ` analyzer.version ` (wire) / ` analyzer_version ` (graph) instead,
120+ because ` [] ` off a 3.2.0 analysis would say "reaches no view" where the truth is that nothing looked.
121+
122+ Measured on daytrader8 with 3.3.3: 37 edges at level 1–2 (3 ` literal ` , 34 ` table ` ), 54 at level 4,
123+ 19 of 23 JSPs reached; the ` TradeConfig.webUI ` table's 17 on-disk pages all reached.
124+
125+ ### Changed
126+
127+ - ` codeanalyzer-java ` pin ` 3.2.0 ` → ** ` 3.3.3 ` ** (the ` java ` extra and ` [tool.backend-versions] ` ).
128+ 3.3.0 adds the view-template role, ` J_DISPATCHES_TO ` , and ` argument_expr ` on ` return ` body nodes;
129+ 3.3.1 the table tier; 3.3.2 narrows the Jakarta entrypoint finder to lifecycle methods, so
130+ helpers taking servlet-typed parameters are no longer entrypoints and the interprocedural
131+ config-use and view-dispatch tiers bind their parameters (daytrader8 entrypoint marks
132+ 135 → 196: 21 helpers dropped, 82 ` init ` /` destroy ` /` doFilter ` /` onMessage ` gained); 3.3.3 fixes
133+ the ` NullPointerException ` 3.3.0–3.3.2 threw on any unbuilt project with a dispatch call, which
134+ this SDK's ` test_java_degradation.py ` was the first to hit (codeanalyzer-java #265 ).
135+ - ` release/2.0 ` absorbed ` main ` at rc.6.
136+
137+ ### Verification
138+
139+ The Java suite offline on both backends over a1 with the layer injected (edges, suffix filter,
140+ dispatcher resolution, the JSON-only refusal on the graph, the pre-3.3.0 refusal, the empty answer
141+ on a 3.3.x payload that reaches nothing, and the answered-once check across backends); the public
142+ surface pins the three signatures; e2e against the 3.3.3 wheel on daytrader8 at level 1 and 2
143+ asserts the 37 edges, the 19 views, the three unresolved URLs and the 38 view-template artifacts.
144+
8145## [ v2.0.0-rc.6] - 2026-09-10
9146
10147The Java Neo4j backend stops being the lossy one about source text. Until now a graph-backed Java
0 commit comments