docs(spec): <app> becomes the outermost can:// segment; the root gets an id - #68
Open
rahlk wants to merge 2 commits into
Open
docs(spec): <app> becomes the outermost can:// segment; the root gets an id#68rahlk wants to merge 2 commits into
rahlk wants to merge 2 commits into
Conversation
… an id Two identity defects, designed together because the second is only half-useful without the first and they share one migration. The deployment unit moves outermost — `can://<app>/<lang>/<file>/...` — so a unit written in two languages stops fragmenting into unrelated id roots. And the application root finally carries the `can://` id it already emits in `analysis.json`: the Neo4j projection drops it today, merging `:JApplication` on free-text `--app-name`, so two services sharing a name silently unify, the root is unaddressable by id, and it is the one node the prefix-scoped destructive statements structurally cannot reach. Supersedes can-uri-service-segment.md, whose positional argument survives but whose cost table and version decision did not: it recorded codeanalyzer-java and python-sdk as unaffected when they now hold 180 and 372 `can://` references, and justified a MINOR bump for a breaking id change on the grounds that no consumer held an id. Names the segment `<app>`, not `<service>` — a monolith has no service, and that also deletes the predecessor's `--app-name` → `--service` rename entirely. Proposes this change carry the coordinated re-baseline #50 has been waiting for: schema_version and the graph contract both to 3.0.0, in lockstep across every analyzer. #50 has had no forcing function; a breaking change that must land everywhere at once is one. Explicitly not part of codeanalyzer-java 3.1.1, which is a patch carrying an opt-in CLI flag.
The maintainer's call, with the costs on the table: the grammar fragments until the sibling analyzers follow, a breaking id change ships under a PATCH number, and python-sdk's pin bump becomes a fixture migration rather than a version edit. Recorded rather than re-argued. The paragraph that said this must not ride 3.1.1 is marked as deliberately overridden, not resolved — so a later reader sees the objection and the override, not a spec that never raised it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Answers two things surfaced while releasing codeanalyzer-java 3.1.x: a multi-service application is queryable but not addressable, and the graph's application root carries no id at all.
A — the deployment unit moves outermost
With
<lang>outermost, one unit written in two languages fragments intocan://python/…andcan://typescript/…with nothing joining them.B — the application root gets its id
analysis.jsonalready emitsapplication.id=can://java/daytrader8. The Neo4j projection drops it::JApplicationmerges onname, the raw--app-namestring, and has noidproperty. codeanalyzer-python's:PyApplicationis identical. Three live defects follow — two services sharing a name silently merge into one node; the root cannot be reached by id; and it is the one node the prefix-scoped destructive statements structurally cannot see, becauseRowBuilderattaches the:JCanNodeindex anchor only to values starting withcan://.Supersedes the Aug 7 spec, and why
can-uri-service-segment.mdproposed the same positional change. That argument survives; two others did not.codeanalyzer-javacan://ids at all"python-sdkcan://references"release/2.0Its D3 shipped a breaking id change as MINOR
2.1.0, justified by "no consumer holds acan://id today." Every clause of that is now false. The window it called "the cheapest it will ever be" closed while it sat in draft.It also could not have known about
2026-09-02-prune-scope-on-can-id-prefix.md: destructive statements are now scoped on the id prefix, so the outermost segment is load-bearing for a safety mechanism, not just identity.<app>, not<service>A monolith has no service. That name would force a category error on most projects. The concept the positional argument needs is the unit built and deployed together — one for a monolith, one per service — and CLDK already calls that
app. Keeping it deletes the predecessor's--app-name→--servicerename entirely, so this version is strictly cheaper.Two things that get better, not just fixed
can://artifact/<app>/<path>— a third outermost shape, neither lang nor app. It becomescan://<app>/artifact/<path>. One rule instead of three.can://<app>/covers every node of that app in every language — what the scoping spec wanted and could not have.Proposes carrying #50
The graph contract is held at
2.0.0pending "a coordinated re-baseline across all three analyzers" (#50), which has had no forcing function. This is one: breaking, touches every analyzer, must land in lockstep or the grammar fragments. So bothschema_versionand the graph contract move to 3.0.0 together.Not part of codeanalyzer-java 3.1.1
3.1.1 is a patch carrying an opt-in CLI flag. Shipping a MAJOR contract break under it would be dishonest versioning.
Open for review
Decomposition (§6) is proposed, not decided — six children across the keystone, three analyzers, the SDK and docs, with a hard lockstep requirement. Migration (§5) is the sharp edge: L1 caches, persisted
analysis.jsonand existing Neo4j graphs are all invalidated, and old graphs cannot be cleaned by the new scoped delete because the prefix differs.