Repository navigation
Description
Spec: codellm-devkit/.github → docs/design/specs/can-uri-service-segment.md
Coordination: codellm-devkit/.github#39
Problem
src/schema/v2/emit.ts:350 builds the application root with the language outermost:
const appId = `can://${LANGUAGE}/${appName}`;so every durable id is can://typescript/<app>/<file>/<type>/<sig>, with no deployment
dimension. A polyglot microservice therefore has no single id root — its TypeScript and Python
halves land under unrelated authorities — and cocoa has had to build one outside the schema
(cocoa/system/facts.py:39 wraps our id as fn:<service>/can://…).
Per the spec, <service> becomes the outermost segment and <app> collapses into it:
before can://typescript/<app>/<file>/<type>/<sig>
after can://<service>/typescript/<file>/<type>/<sig>
Scope boundary
This repo only. Does not add cross-service edges (no RPC/HTTP call family — Epic E), does not
touch the keystone grammar docs, does not touch cocoa, and does not touch codeanalyzer-python
(its own issue). The can:// scheme name is settled and not in scope.
Does not attempt to reconcile the two known sibling divergences recorded in the
codeanalyzer-dotnet spec — UTF-16 vs UTF-8 span offsets, and unprefixed vs per-language Neo4j
labels. Both are real, both make this repo the outlier, and both are their own design session.
Goals
-
src/schema/v2/emit.ts:350— service becomes the outermost segment;<app>removed -
src/schema/v2/model.ts:39— theid: string; // can://<lang>/<app>comment follows -
src/cli.ts:19—--app-name <name>→--service <name>, same default (input dir name);
src/options/options.ts:15appNamerenamed with it -
src/build/neo4j/schema.ts—SCHEMA_VERSION→"2.1.0";CanNodekeys follow the ids -
homeExternals(emit.ts:301) — verify@externalids still compose fromappIdwith no
logic change:can://<service>/typescript/@external/<module>/<name> - Anonymous-callback ordinal ids (
<enclosing-can-id>@<line>:<col>) unchanged - v2 tests +
test/neo4j-schema.test.tsconformance updated
Caveats and known risks
- The version number understates the break. 2.1.0 is MINOR for a change that rewrites every
durable id and theCanNodeMERGE key — this repo's own rule insrc/build/neo4j/schema.ts
says MAJOR on a renamed key. Deliberate erratum, valid only because no consumer holds a
can://id today (typescript-sdkis pre-v2, zero references). Not precedent later. - Persisted Neo4j graphs need a full re-ingest, not an incremental
MERGE. - Shared code is analyzed once per service by design: one run per service (spec D5).
- Renaming
--app-nameis a CLI break for existing callers. Whether to keep a deprecated
alias is an open call the spec does not decide. - Must land in lockstep with
codeanalyzer-python's equivalent change;cocoais gated on both.
Definition of done
- A no-flag run on a TS project emits
can://<dir-name>/typescript/src/…— verified on a
real run, not an asserted shape -
--service checkoutemitscan://checkout/typescript/src/cart.ts/CartService/checkout(userId) - No emitted id contains an
<app>segment distinct from the service - External library targets resolve as
can://<service>/typescript/@external/<module>/<name>
and everycalleebackfilled at L2 points at a resolvable id - Every edge endpoint resolves —
call_graph,extends_ids/implements_ids,
param_in/param_out— with zero dangling references - Ordinal ids below the callable unchanged, including anonymous callbacks
-
schema_versionreads"2.1.0"in both the JSON envelope and the Neo4j contract -
test/neo4j-schema.test.tspasses — the emitter produces no undeclared label,
relationship, or property
Activity
rahlk commentedon Aug 19, 2026
Version reshuffle: this moves to schema 2.2.0.
#92 (materialize anonymous callables as first-class callables) takes 2.1.0 instead. Rationale: the EXP-001 Juice Shop dataflow measurement is blocked behind #92 — no
req.body.emailfact reaches the DDG until anonymous handlers are graphed — whereas the<service>segment is acocoa-facing identity concern with no analysis blocked behind it.No design conflict between the two. #92 changes the id suffix (a
<anon@L:C>segment contributed under the enclosing callable); this issue changes the id prefix. Orthogonal productions, so whichever merges second rebases without a semantic collision. Both remain provisional pending roadmap candidate 4 (can://grammar conformance, collision group A).Spec for #92:
docs/design/specs/anonymous-callable-materialization.mdrahlk commentedon Aug 20, 2026
Won't fix — the
<app>segment stays. Closed in lockstep with codellm-devkit/codeanalyzer-python#123 and the parent epic codellm-devkit/.github#39;codeanalyzer-pythonis the reference implementation for the identity grammar and it is keepingcan://<lang>/<app>/….