Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,74 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v2.0.0-rc.6] - 2026-09-10

The Java Neo4j backend stops being the lossy one about source text. Until now a graph-backed Java
analysis could answer *where* a node is far better than *what it says*: text existed only as
`:JCallable.code`, so a callable came back as its whole declaration where the local backend returned
the body block, a body node had no text at all, and a module-scope `locate` returned `""`. The
analyzer closed that gap in 3.2.0; this release takes it up, and moves the sibling pins to the
releases that closed the same gap for Python and TypeScript.

### Breaking

**The Java Neo4j attach floor moves to codeanalyzer-java 3.2.0.** A graph emitted by 3.1.x — served
silently until now — is refused at attach, naming what was found and the floor.

The floor moves rather than degrading gracefully because the degradation would be silent and would
look like data. A 3.1.x graph has no `:JModule.source` and no byte offsets, so every text answer
would come back empty or as the old whole-declaration string, from accessors this release documents
as returning the same text as the local backend. An agent cannot tell "this node has no text" from
"this graph predates the property" — so the check belongs at attach, once, where it can say so.

**Migration:** re-emit with `codeanalyzer-java 3.2.0 --emit neo4j`. Wipe the database first when the
graph predates 3.1.1, which moved the `can://` grammar.

### Changed

**Text is the same on both Java backends.** `JCallable.code`, `get_source`, `LocateResult.source` and
`describe` answer the same slice of the same file at every granularity — a callable's body block, a
type's or field's or local's declaration, a single statement or call site, and a module's whole text at
module scope. Each is a byte slice of `:JModule.source` taken at the node's own offsets, so the live
suites assert **equality** rather than `endswith` or "the same length".

Three positions still have no text, on **both** backends and for the same reason each time — there is
nothing in the file to point at: an implicit compiler-generated `<init>()`, an `@external` callable, and
a `resolve_value` ref (a `formal_in` vertex is a dataflow position, not a region of the file).
`module_source_unavailable` survives as a **data** diagnostic: it now fires on a module whose text the
analyzer could not read or decode, and on nothing else.

Two removals fall out of it. `:JCallable.code` is no longer read — the slice replaces it — and
`body_end_byte` was never needed: across both committed fixtures, all 1,182 callables carrying both
spans end their body exactly where their declaration ends, because a Java declaration's last character
*is* its body's closing brace. That is asserted in the fixture builder rather than written down.

**Analyzer pins move to `codeanalyzer-python==1.5.2` and `codeanalyzer-typescript==1.6.0`**
(`codeanalyzer-java` is already at 3.2.0). Both are Neo4j-projection-only conformance fixes: python
1.5.2 adds `:PyModule.source`, all six span properties wherever a span is declared,
`:PyVariable.value_json`, `:PyBodyNode.callee_signature`, `PY_IMPORTS.positions_json` and a span on
`PY_DECORATED_BY`; typescript 1.6.0 adds `:TSModule.source` and the four new span properties across ten
labels. Neither changes `analysis.json` — the TypeScript fixtures regenerated with the 1.6.0 wheel are
byte-identical to the 1.5.3 generation at all four levels apart from the `analyzer.version` stamp.

**Neither sibling floor moves.** They stay 1.5.0 for Python and 1.5.2 for TypeScript: a floor move is
what would let the SDK *read* that new text, and that is uptake work the size of this release's Java
half, tracked in #396 and #391. The pin is what the SDK installs; the floor is what it requires of a
graph. Every sentence in the docs that read "the graph does not carry this" now says the SDK does not
read it, and names the issue that will.

One thing does improve for free on a re-emitted Python graph: a call site's columns. The
reconstruction already reads `start_column` with a `-1` default, so 1.5.2 supplies real values and an
older graph still answers `-1` — data-driven, no version branch.

### Verification

The mocked, backend-contract and E2E tiers are green, and the Java E2E ran against the real 3.2.0 jar.
The **live** Java tiers — the ones that assert byte-for-byte equality across the two backends on
daytrader8 — assert the new behaviour but have not been run against a 3.2.0-emitted graph: the
verification corpus holds a 3.1.1 graph, which this release's own floor now refuses. Re-emitting it is
the outstanding verification debt, recorded rather than glossed.

## [v2.0.0-rc.5] - 2026-09-10

Two changes, and they are the two halves of one question: what should happen when an analyzer ships
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "cldk"
version = "2.0.0-rc.5"
version = "2.0.0-rc.6"
description = "The official Python SDK for Codellm-Devkit."
readme = "README.md"
license = { text = "Apache-2.0" }
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.