Repository navigation
Description
Is your feature request related to a problem? Please describe.
After 2.5a the TypeScript layer reads schema v2 on both backends, but it exposes only the 1.x vocabulary. Python gained an agent-facing query surface in legs 1.5 and 1.6; TypeScript has none of it. Measured on the branch: PythonAnalysis has 59 public accessors, TypeScriptAnalysis has 46, and 31 of the difference is this leg's scope.
The analyzer gate is closed: codeanalyzer-typescript 1.3.0 shipped 2026-09-06, landing the L4 port-lattice fix (#169), body-node and parameter ids (#165), the retirement of _module (#166) and the entrypoint report. 2.5a pinned 1.2.0 deliberately, because the SDK pins only released analyzers.
Describe the solution you'd like
- TS-1:
LocateResult's Python-typed body-node field becomes a language-neutralBodyRef{id, kind, span, callee}populated from either analyzer, withcldk/analysis/commons/results.pyno longer importingcldk.models.python - TS-2: the dataflow surface with Python's bounds — depth defaults to a finite value on slices only, predicates and paths unbounded, one completeness protocol, no suggestions or fuzzy matching on any error path
- Addressing and
describe, keyed by the same vocabulary the 2.5a accessors return, with nocan://in any signature, return field other thanref/node_id/next_cursor, or message - The entrypoint trio, over 1.3.0's entrypoint report
- Both backends answer identically, including on the miss paths, over the same application
- Pin
codeanalyzer-typescript==1.3.0; the probe's floor moves with it and refuses a graph below it - The multi-application audit covers every new statement, both prefixes
Describe alternatives you've considered
Not stated in the original issue.
Additional context
Plan (optional)
Spec: docs/design/specs/2026-09-06-leg-2.5-typescript.md — decisions TS-1, TS-2, TS-3 and the 2.5b half of TS-4. Plan to follow at docs/design/plans/. Builds on #335 (2.5a).
Scope boundary
In scope, all on both backends, with Python's semantics: addressing (locate, locate_many, resolve_callable, resolve_value, get_source, describe); per-callable graphs (get_cfg, get_cdg, get_ddg) as paginated EdgePages; dataflow and reachability (slice_backward, slice_forward, backward_cone, reaches, callers_of, callees_of, paths_between, call_paths_between, flows_to_call, flows_to_argument); has_resolution_edges; the entrypoint trio (get_entrypoints, get_entrypoint_classes, get_entrypoint_coverage) replacing the two accessors 2.5a removed; the artifact and config layer (get_artifacts, get_dependencies, get_config_keys, get_config_uses, get_unresolved_config_reads, get_config_readers) on the facade; scoping keywords on the existing accessors; SelectorNotInGraph and AmbiguousName; TS-1's neutral body reference on the shared LocateResult; the pin bump to 1.3.0; the agent reference's TypeScript query section.
Out of scope: anything Java (#310, #311); the cross-language query sweep; analyzer work.
Caveats and known risks
- 1.3.0 makes
entrypoint_reportrequired on the application, where 1.2.0 omitted it. 2.5a modelled it optional precisely so one model parses both generations, so the bump should not move the models — verify rather than assume. - 1.3.0 may stamp
is_entrypointon any type kind. 2.5a's fix round moved that field onto the shared type base for exactly this reason; a payload that stamps it elsewhere would still failextra="forbid"loudly. - The reference graph must be re-emitted with the released 1.3.0 wheel: the 2.5a graph came from a
mainsource build that stamps1.2.0, so it cannot exercise a 1.3.0 floor. - Java's leg-3a experience says a corpus without local classes hides a whole class of key-collision defect. Check the TypeScript equivalent (anonymous and arrow callables, declaration merging) against a scale corpus, not only the sample app.
Definition of done
- Every accessor above answers identically on
TSCodeanalyzerandTSNeo4jBackendover the same application, with the same diagnostics on the miss paths - The public-surface test's frozen list grows by exactly the accessors this leg adds, and nothing pre-existing moves
-
GraphSchemaMismatchon a graph below the 1.3.0 floor; the multi-application audit green over both prefixes - Bounds never silent: a truncated result says so through the completeness protocol
- Release gate green; agent reference and CHANGELOG updated
Activity
python-sdk2.0 — a static-analysis front end for humans and agents .github#55rahlk commentedon Sep 7, 2026
codeanalyzer-typescript 1.4.0 is out (https://github.com/codellm-devkit/codeanalyzer-typescript/releases/tag/v1.4.0) and carries the data this leg's accessors need over Neo4j, so the pin for 2.5b should land on 1.4.0 rather than 1.3.0:
get_imports/get_exports:TS_IMPORTSandTS_RE_EXPORTS, one relationship per (module, target) withspellings[],imported_names[]/exported_names[],aliases[],type_only_names[]— python'sPY_IMPORTSaggregation rule; externals on the@external/<package root>ghost.exports_jsonon:TSModuleis the verbatimexports[]list.analysis.jsongainsresolved_moduleon imports/re-exports.get_method_parameters:parameters_jsonon:TSCallable, python's encoding —reconstruct.callable_already decodes it, so the documented tolerance can go.get_config_readers/ unresolved reads:TS_READS_CONFIG_UNRESOLVED:TSApplication → :TSExternal | :TSCallable,key/reason/prov,_k = key|reason, nosite—PY_READS_CONFIG_UNRESOLVED's shape, same per-site collapse. (TS_USES_CONFIGwas already there.)Contract stays
2.0.0;analyzer_versionis what the probe should pin. Decision record:docs/design/specs/neo4j-bindings-parameters-config.mdon that repo (codeanalyzer-typescript #182 / PR #183).rahlk commentedon Sep 7, 2026
codeanalyzer-typescript 1.5.0 (https://github.com/codellm-devkit/codeanalyzer-typescript/releases/tag/v1.5.0) closes #179 and #177 on the analyzer side; two things for this leg's pin:
span.bytesare UTF-8 byte offsets now, every node and level (it was UTF-16 char offsets, mis-documented). Slice the TypeScript leg exactly as the python side already does —source.encode("utf-8")[lo:hi]— one rule across languages.:TSCallable.codeis byte-exact, so the fourxfail(strict=True)marks intest_typescript_bulk_parity_live.pyshould flip on this pin. Files with no non-ASCII character are byte-identical to 1.4.0; any other file's spans after the first multibyte char moved.…/Name#type; a later type facet of a type/type merge is keyedName#<kind>intypes{}(C#interface) with id…/C#interface. Ids only moved where they collided before; signatures are unchanged. Atypes{}model keyed by name should accept the#<kind>keys.Also in 1.5.0: finalize no longer
structuredClones the whole envelope (#180, vscode-scale runs complete) and a missing-ipath exits 1 with nothing written (#181). Records:docs/design/specs/span-bytes-are-bytes.md,docs/design/specs/declaration-merging-ids.md.