Skip to content
Open
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
127 changes: 126 additions & 1 deletion docs/design/roadmap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CLDK roadmap

**Pass:** 2026-08-07
**Pass:** 2026-08-07 (schema v2 consistency) · amended 2026-09-11 (Java web layer, below)
**Planned with:** Rahul Krishna
**Status:** current (supersede by editing, not by adding a second roadmap)

Expand Down Expand Up @@ -208,3 +208,128 @@ spec-only pass has no pull request to close. The first epic under this roadmap w
whichever of candidates 7 through 11 is picked up once Group A's spec exists to point at.

Everything else on this roadmap has no issue yet, by design.

---

# Pass 2026-09-11 — the Java web layer

**Planned with:** Rahul Krishna

Theme: **make the view layer of a Java web application reachable in the graph** — JSP,
servlets and their descriptors, Thymeleaf, JSF/Facelets. Prompted by an exploitability run
over DayTrader (`codeanalyzer-java` 3.2.0) whose findings skewed to build and deployment
files because the analyzer "read `src/main/java` only — JSP was never parsed."

## The finding

The claim is half right. The symbol table walks `src/*/java` roots only, but the
repository-artifact layer (#45) already inventories every JSP with its **full source**
(`format: text`, `roles: ["unknown"]`) and `web.xml` too (`roles: ["tool-config"]`, never
parsed). The bytes are in the graph; the structure is not. Measured on DayTrader:

- 23 `.jsp` files against 141 `.java`; 348 `<%= %>` expressions (XSS sinks) and 14
`request.getParameter` reads inside JSPs (taint sources) with no node of any kind;
- 33 distinct `.jsp` strings in the graph, all as **text** — servlets reach their views
through `getRequestDispatcher("/x.jsp").forward(...)` and the SDG stops at the string
literal, never at the artifact;
- no template is an entrypoint and no entrypoint has a URL: `web.xml` servlet-mappings and
welcome-files are unread, and Spring `@RequestMapping` arguments sit raw in decorators.

The servlet side needs no new contract: `javaee/` already ships Jakarta, Spring, JAX-RS,
Struts and Camel entrypoint finders, and DayTrader's 151 entrypoints come from them. The
gap is entirely the view side — and it is not Java-specific. `codeanalyzer-python` has no
template role either (Jinja/Django) and `codeanalyzer-typescript` none for Vue/Svelte, so
whatever Java coins here is the vocabulary the other two inherit.

## Candidates

Numbering continues from the first pass.

| # | Feature | Moves schema v2? | Collision group | Blocked by |
| - | ------- | ---------------- | --------------- | ---------- |
| 16 | **View-template artifact role** — `.jsp`, `.xhtml`, Thymeleaf `.html`, and the like classified instead of `unknown` | yes — the shared open `roles` vocabulary, which #48 says is itself unreconciled | D | #48 (folded in) |
| 17 | **View-dispatch edges** — `forward` / `include` / `sendRedirect` / `ModelAndView` / returned view name / JSF navigation outcome, from a callable or body node to the `Artifact`; view-name resolution needs the Spring/Thymeleaf prefix and suffix from config keys | yes — a new edge kind; `J_USES_CONFIG` is the precedent (language-prefixed source, un-prefixed target, `prov`) | D | 16 |
| 18 | **Descriptor-derived routes** — `web.xml` servlet/filter/welcome-file/error-page mappings and `faces-config.xml` navigation as a URL on the entrypoint, unified with annotation-derived routes (`@RequestMapping`, `@Path`) | yes — a route field on entrypoints; no analyzer has one | E | 6 (first pass) |
| 19 | **Template-internal code model** — how `<%= %>`, `${...}`, `th:*`, `#{...}` appear as nodes with spans beneath a non-code file: the node kind and the id grammar under an artifact | yes — a new kind in the shared ladder and a new id shape | F | 16 |
| 20 | **Template ↔ code dataflow** — `request.setAttribute` / `model.addAttribute` / managed-bean properties bound to template reads, and in-template `getParameter` as an SDG source | yes — `ddg` endpoints on template nodes, new `prov` values | F | 17, 19 |
| 21 | Bundler output inventory — `static/`, `dist/` JS and CSS as artifacts with a role | yes — same `roles` vocabulary as 16 | D | — |
| 22 | JSF and Thymeleaf entrypoint finders — `@Named` / `@ManagedBean`; `@Controller` already matches | **no** — an additive `entrypoint_frameworks` value | — | — |

Candidate 22 is not a contract decision; it is a maintenance-rung item recorded so it is not
mistaken for one. It ships with 18.

## Collision groups

- **Group D — template-as-artifact vocabulary**: candidates 16, 17, 21.

One role name and one edge name, coined once for three analyzers: python's
`render_template("x.html")` and TypeScript's SFC imports are the same edge from the same
role. The session **also settles #48** — the `roles` vocabulary is still contested between
the spec's closed `artifact_kind` and the shipped open `roles[]`, and a role coined on a
contested vocabulary is the one planning mistake the parity clause makes permanent. So the
spec amendment that resolves #48 and the spec that coins the template role are one PR.

- **Group E — entrypoint route vocabulary**: candidate 18.

The first pass's candidate 6 (entrypoint vocabulary, Group B) settled `is_entrypoint`,
`entrypoint_frameworks` and the entrypoint report; it did not give an entrypoint a URL.
Routes are where the microservice initiative's service boundaries begin, so this is the
hand-off point to that deferred work, decided once across descriptor-derived and
annotation-derived sources. One twist reaches back into Group D: a welcome-file JSP is
itself URL-addressable, so an `Artifact` can be an entrypoint, and E's field has to be
legal on D's node.

- **Group F — template code model**: candidates 19, 20.

One decision for JSP, Thymeleaf and Facelets; per-engine extractors are additive under
it. Jasper/JspC translation to a generated servlet is one option *inside* this session
(real callables, but spans that point at generated lines, not the JSP), not a candidate of
its own.

## Dependency order

#48 ──┐
├─▶ 16 role ──▶ 17 dispatch edges ──┐
│ ├─▶ 20 template ↔ code dataflow
└─▶ 19 template code model ┘

6 (first pass, Group B) ──▶ 18 routes [Group E; bridges to the microservice initiative]

21 bundler inventory — not now (below)
22 finders — rides with 18, no contract

Group D unblocks everything else on this pass and needs nothing new: every fact it
projects — the JSP text, the `web.xml` text, the string literal at the dispatch call site —
is already in the graph. Group E is independent of D and can run in parallel; Group F
cannot start until the role exists to hang nodes under.

## Release trains

| Train | Carries | Notes |
| ----- | ------- | ----- |
| `codellm-devkit/.github` spec | #48 resolution + 16, 17 | one spec PR; the vocabulary is what the other analyzers inherit |
| `codeanalyzer-java` 3.3.0 | 16, 17 | additive MINOR — a role value, an edge kind; `schema_version` stays 2.0.0 pending the coordinated re-baseline (#50) |
| `codeanalyzer-java` 3.4.0 | 18, 22 | additive MINOR |
| `codeanalyzer-java` next | 19, 20 | additive — new kind under an artifact; whether it is a MINOR depends on the id grammar Group F chooses |
| `python-sdk` | 16–20 as they land | the reconstructor and facade grow with each; a template node kind (19) is the first that needs a new model |
| `codeanalyzer-python`, `codeanalyzer-typescript` | 16, 17 vocabulary only | no work scheduled; they adopt the names when they grow templates (Not now) |

## Not now

- **Candidate 21, bundler output inventory** — inventory-only value; built JS is
`codeanalyzer-typescript`'s turf, and a Java repository that also carries a frontend is the
multi-language case the deferred microservice initiative owns. The role, if one is ever
coined, belongs to Group D's vocabulary and is recorded here so it is coined there.
- **Python and TypeScript templates** — Jinja/Django, Vue/Svelte SFCs. Same vocabulary,
different repos; they adopt Group D's names when they start, and nothing here schedules
them.
- **Freemarker / Velocity / Struts Tiles** — not in this pass's scope. Additive engines
under Group F's model if wanted later.
- **Frontend bundler analysis** (as opposed to inventory) — never Java's; TypeScript's.

## Starting now

**Group D — candidates 16 and 17, with #48 folded in.** Enters `designing-cldk-changes`;
the epic is filed when implementation starts, not before.

Everything else on this pass has no issue yet, by design.
Loading