@telorun/analyzer 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,20 +54,13 @@ metadata:
54
54
  description: |
55
55
  A complete feedback collection REST API — no code, pure YAML.
56
56
  Persists entries to SQLite and serves them over HTTP.
57
+ imports:
58
+ Http: std/http-server@0.6.1
59
+ Sql: std/sql@0.5.1
57
60
  targets:
58
61
  - Migrations
59
62
  - Server
60
63
  ---
61
- kind: Telo.Import
62
- metadata:
63
- name: Http
64
- source: std/http-server@0.5.0
65
- ---
66
- kind: Telo.Import
67
- metadata:
68
- name: Sql
69
- source: std/sql@0.3.0
70
- ---
71
64
  # SQLite database — swap driver/host/database for PostgreSQL with zero YAML changes
72
65
  kind: Sql.Connection
73
66
  metadata:
@@ -127,7 +120,7 @@ routes:
127
120
  minLength: 1
128
121
  source:
129
122
  type: string
130
- required: [text]
123
+ required: [ text ]
131
124
  handler:
132
125
  kind: Sql.Exec
133
126
  connection:
@@ -157,7 +150,7 @@ routes:
157
150
  kind: Sql.Connection
158
151
  name: Db
159
152
  from: feedback
160
- columns: [id, text, source, score, created_at]
153
+ columns: [ id, text, source, score, created_at ]
161
154
  orderBy:
162
155
  - { column: created_at, direction: desc }
163
156
  response:
@@ -176,14 +169,14 @@ routes:
176
169
  properties:
177
170
  id:
178
171
  type: integer
179
- required: [id]
172
+ required: [ id ]
180
173
  handler:
181
174
  kind: Sql.Select
182
175
  connection:
183
176
  kind: Sql.Connection
184
177
  name: Db
185
178
  from: feedback
186
- columns: [id, text, source, score, created_at]
179
+ columns: [ id, text, source, score, created_at ]
187
180
  where:
188
181
  - { column: id, op: "=", value: "${{ request.params.id }}" }
189
182
  response:
@@ -1,9 +1,31 @@
1
1
  import type { ResourceManifest } from "@telorun/sdk";
2
2
  import type { LoadedGraph, LoadedModule } from "./loaded-types.js";
3
+ /** The import-boundary forwarding rule, shared by `flattenForAnalyzer` (the
4
+ * CLI / kernel loader path) and the telo-editor's workspace projection so the
5
+ * two cannot drift. Given one module's stamped manifests and whether that
6
+ * module is the analysis entry (root), returns the manifests that cross into
7
+ * the consumer's flat analysis list:
8
+ *
9
+ * - **Root module** — every manifest is local; returned unchanged. The root's
10
+ * internals (CEL / schema / refs) are validated in full.
11
+ * - **Imported module** — only `Telo.Definition` / `Telo.Abstract` /
12
+ * `Telo.Import` docs cross unconditionally, plus the instances named in the
13
+ * module's `exports.resources` (stamped `metadata.forwardedExport: true`).
14
+ * The module doc and internal (unexported) instances are dropped — they
15
+ * belong to that module's own analysis pass.
16
+ *
17
+ * `forwardedExport` marks an instance as a cross-module resolution TARGET only
18
+ * (keyed by `metadata.module`), so `resolveRefSentinels` files it under
19
+ * `byModuleName` and `!ref Alias.name` resolves, while `validate-references` /
20
+ * the per-resource validation loop never re-walk or re-validate it against the
21
+ * consumer's scope. A consumer that instead emits every module doc as a peer
22
+ * local manifest silently breaks both. */
23
+ export declare function selectModuleManifestsForAnalysis(moduleManifests: ResourceManifest[], isRoot: boolean): ResourceManifest[];
3
24
  /** Produce the flat manifest list `analyze()` consumes today.
4
25
  *
5
26
  * Combines the entry module's manifests with `Telo.Definition`,
6
- * `Telo.Abstract`, and `Telo.Import` docs forwarded from imported libraries.
27
+ * `Telo.Abstract`, and `Telo.Import` docs forwarded from imported libraries
28
+ * (plus their `exports.resources` instances) via `selectModuleManifestsForAnalysis`.
7
29
  * Stamps three flavours of metadata along the way:
8
30
  *
9
31
  * - `metadata.source` and `metadata.sourceLine` — already on each manifest
@@ -1 +1 @@
1
- {"version":3,"file":"flatten-for-analyzer.d.ts","sourceRoot":"","sources":["../src/flatten-for-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAc,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG/E;;;;;;;;;;;;;;;;;;6EAkB6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,EAAE,CA6EzE;AAED;;;;;6BAK6B;AAC7B,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,gBAAgB,EAAE,CAEzE"}
1
+ {"version":3,"file":"flatten-for-analyzer.d.ts","sourceRoot":"","sources":["../src/flatten-for-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAc,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG/E;;;;;;;;;;;;;;;;;;;2CAmB2C;AAC3C,wBAAgB,gCAAgC,CAC9C,eAAe,EAAE,gBAAgB,EAAE,EACnC,MAAM,EAAE,OAAO,GACd,gBAAgB,EAAE,CAwBpB;AAED;;;;;;;;;;;;;;;;;;;6EAmB6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,EAAE,CA+CzE;AAED;;;;;6BAK6B;AAC7B,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,gBAAgB,EAAE,CAEzE"}
@@ -1,8 +1,50 @@
1
1
  import { isModuleKind } from "./module-kinds.js";
2
+ /** The import-boundary forwarding rule, shared by `flattenForAnalyzer` (the
3
+ * CLI / kernel loader path) and the telo-editor's workspace projection so the
4
+ * two cannot drift. Given one module's stamped manifests and whether that
5
+ * module is the analysis entry (root), returns the manifests that cross into
6
+ * the consumer's flat analysis list:
7
+ *
8
+ * - **Root module** — every manifest is local; returned unchanged. The root's
9
+ * internals (CEL / schema / refs) are validated in full.
10
+ * - **Imported module** — only `Telo.Definition` / `Telo.Abstract` /
11
+ * `Telo.Import` docs cross unconditionally, plus the instances named in the
12
+ * module's `exports.resources` (stamped `metadata.forwardedExport: true`).
13
+ * The module doc and internal (unexported) instances are dropped — they
14
+ * belong to that module's own analysis pass.
15
+ *
16
+ * `forwardedExport` marks an instance as a cross-module resolution TARGET only
17
+ * (keyed by `metadata.module`), so `resolveRefSentinels` files it under
18
+ * `byModuleName` and `!ref Alias.name` resolves, while `validate-references` /
19
+ * the per-resource validation loop never re-walk or re-validate it against the
20
+ * consumer's scope. A consumer that instead emits every module doc as a peer
21
+ * local manifest silently breaks both. */
22
+ export function selectModuleManifestsForAnalysis(moduleManifests, isRoot) {
23
+ if (isRoot)
24
+ return moduleManifests;
25
+ const libDoc = moduleManifests.find((m) => isModuleKind(m.kind));
26
+ const exportedResources = new Set(libDoc?.exports?.resources ?? []);
27
+ const out = [];
28
+ for (const m of moduleManifests) {
29
+ if (m.kind === "Telo.Definition" || m.kind === "Telo.Abstract" || m.kind === "Telo.Import") {
30
+ out.push(m);
31
+ }
32
+ else if (!isModuleKind(m.kind) &&
33
+ typeof m.metadata?.name === "string" &&
34
+ exportedResources.has(m.metadata.name)) {
35
+ out.push({
36
+ ...m,
37
+ metadata: { ...m.metadata, forwardedExport: true },
38
+ });
39
+ }
40
+ }
41
+ return out;
42
+ }
2
43
  /** Produce the flat manifest list `analyze()` consumes today.
3
44
  *
4
45
  * Combines the entry module's manifests with `Telo.Definition`,
5
- * `Telo.Abstract`, and `Telo.Import` docs forwarded from imported libraries.
46
+ * `Telo.Abstract`, and `Telo.Import` docs forwarded from imported libraries
47
+ * (plus their `exports.resources` instances) via `selectModuleManifestsForAnalysis`.
6
48
  * Stamps three flavours of metadata along the way:
7
49
  *
8
50
  * - `metadata.source` and `metadata.sourceLine` — already on each manifest
@@ -20,8 +62,7 @@ import { isModuleKind } from "./module-kinds.js";
20
62
  * callers look it up via `findPositions(graph, ...)` on the LoadedGraph. */
21
63
  export function flattenForAnalyzer(graph) {
22
64
  const result = [];
23
- const stampedEntry = collectModuleManifests(graph.entry);
24
- result.push(...stampedEntry);
65
+ result.push(...selectModuleManifestsForAnalysis(collectModuleManifests(graph.entry), true));
25
66
  const seen = new Set([graph.rootSource]);
26
67
  const queue = [graph.rootSource];
27
68
  while (queue.length > 0) {
@@ -37,31 +78,7 @@ export function flattenForAnalyzer(graph) {
37
78
  const targetModule = graph.modules.get(edge.targetSource);
38
79
  if (!targetModule)
39
80
  continue;
40
- const stamped = collectModuleManifests(targetModule);
41
- const libDoc = stamped.find((m) => isModuleKind(m.kind));
42
- const exportedResources = new Set(libDoc?.exports?.resources ?? []);
43
- for (const m of stamped) {
44
- if (m.kind === "Telo.Definition" ||
45
- m.kind === "Telo.Abstract" ||
46
- m.kind === "Telo.Import") {
47
- result.push(m);
48
- }
49
- else if (!isModuleKind(m.kind) &&
50
- typeof m.metadata?.name === "string" &&
51
- exportedResources.has(m.metadata.name)) {
52
- // Forward instances listed in the library's `exports.resources` so the
53
- // consumer's analyzer can resolve, gate, kind-check, and draw topology edges
54
- // for cross-module `!ref Alias.name`. The gate IS this forwarding — only
55
- // exported names cross the boundary. `metadata.forwardedExport` marks them as
56
- // cross-module resolution targets only (keyed by `metadata.module`), so ref
57
- // resolution / validation treats them as targets, never as local sources to
58
- // re-validate or walk.
59
- result.push({
60
- ...m,
61
- metadata: { ...m.metadata, forwardedExport: true },
62
- });
63
- }
64
- }
81
+ result.push(...selectModuleManifestsForAnalysis(collectModuleManifests(targetModule), false));
65
82
  }
66
83
  }
67
84
  // Stamp resolved import identity on every Telo.Import in the result by
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { AnalysisRegistry } from "./analysis-registry.js";
2
2
  export { StaticAnalyzer } from "./analyzer.js";
3
3
  export type { GraphLoadError, ImportEdge, LoadedFile, LoadedGraph, LoadedModule, ParseError, } from "./loaded-types.js";
4
- export { flattenForAnalyzer, flattenLoadedModule } from "./flatten-for-analyzer.js";
4
+ export { flattenForAnalyzer, flattenLoadedModule, selectModuleManifestsForAnalysis, } from "./flatten-for-analyzer.js";
5
5
  export { visitManifest } from "./manifest-visitor.js";
6
6
  export type { CelSiteEvent, ManifestVisitor, RefSiteEvent, ResourceEnterEvent, ResourceExitEvent, ScopeBoundaryEvent, SchemaFromSiteEvent, VisitOptions, } from "./manifest-visitor.js";
7
7
  export { Loader } from "./manifest-loader.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACR,cAAc,EACd,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,YAAY,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EACH,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC3E,YAAY,EACR,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,QAAQ,EACR,aAAa,EACb,KAAK,EACR,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACR,cAAc,EACd,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,kBAAkB,EAClB,mBAAmB,EACnB,gCAAgC,GACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,YAAY,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EACH,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC3E,YAAY,EACR,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,QAAQ,EACR,aAAa,EACb,KAAK,EACR,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { AnalysisRegistry } from "./analysis-registry.js";
2
2
  export { StaticAnalyzer } from "./analyzer.js";
3
- export { flattenForAnalyzer, flattenLoadedModule } from "./flatten-for-analyzer.js";
3
+ export { flattenForAnalyzer, flattenLoadedModule, selectModuleManifestsForAnalysis, } from "./flatten-for-analyzer.js";
4
4
  export { visitManifest } from "./manifest-visitor.js";
5
5
  export { Loader } from "./manifest-loader.js";
6
6
  export { isModuleKind, MODULE_KINDS } from "./module-kinds.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telorun/analyzer",
3
- "version": "0.16.1",
3
+ "version": "0.17.0",
4
4
  "description": "Telo Analyzer - Static manifest validator for Telo manifests.",
5
5
  "keywords": [
6
6
  "telo",
@@ -2,10 +2,60 @@ import type { ResourceManifest } from "@telorun/sdk";
2
2
  import type { LoadedFile, LoadedGraph, LoadedModule } from "./loaded-types.js";
3
3
  import { isModuleKind } from "./module-kinds.js";
4
4
 
5
+ /** The import-boundary forwarding rule, shared by `flattenForAnalyzer` (the
6
+ * CLI / kernel loader path) and the telo-editor's workspace projection so the
7
+ * two cannot drift. Given one module's stamped manifests and whether that
8
+ * module is the analysis entry (root), returns the manifests that cross into
9
+ * the consumer's flat analysis list:
10
+ *
11
+ * - **Root module** — every manifest is local; returned unchanged. The root's
12
+ * internals (CEL / schema / refs) are validated in full.
13
+ * - **Imported module** — only `Telo.Definition` / `Telo.Abstract` /
14
+ * `Telo.Import` docs cross unconditionally, plus the instances named in the
15
+ * module's `exports.resources` (stamped `metadata.forwardedExport: true`).
16
+ * The module doc and internal (unexported) instances are dropped — they
17
+ * belong to that module's own analysis pass.
18
+ *
19
+ * `forwardedExport` marks an instance as a cross-module resolution TARGET only
20
+ * (keyed by `metadata.module`), so `resolveRefSentinels` files it under
21
+ * `byModuleName` and `!ref Alias.name` resolves, while `validate-references` /
22
+ * the per-resource validation loop never re-walk or re-validate it against the
23
+ * consumer's scope. A consumer that instead emits every module doc as a peer
24
+ * local manifest silently breaks both. */
25
+ export function selectModuleManifestsForAnalysis(
26
+ moduleManifests: ResourceManifest[],
27
+ isRoot: boolean,
28
+ ): ResourceManifest[] {
29
+ if (isRoot) return moduleManifests;
30
+
31
+ const libDoc = moduleManifests.find((m) => isModuleKind(m.kind));
32
+ const exportedResources = new Set<string>(
33
+ (libDoc as { exports?: { resources?: string[] } } | undefined)?.exports?.resources ?? [],
34
+ );
35
+
36
+ const out: ResourceManifest[] = [];
37
+ for (const m of moduleManifests) {
38
+ if (m.kind === "Telo.Definition" || m.kind === "Telo.Abstract" || m.kind === "Telo.Import") {
39
+ out.push(m);
40
+ } else if (
41
+ !isModuleKind(m.kind) &&
42
+ typeof m.metadata?.name === "string" &&
43
+ exportedResources.has(m.metadata.name as string)
44
+ ) {
45
+ out.push({
46
+ ...m,
47
+ metadata: { ...m.metadata, forwardedExport: true } as ResourceManifest["metadata"],
48
+ });
49
+ }
50
+ }
51
+ return out;
52
+ }
53
+
5
54
  /** Produce the flat manifest list `analyze()` consumes today.
6
55
  *
7
56
  * Combines the entry module's manifests with `Telo.Definition`,
8
- * `Telo.Abstract`, and `Telo.Import` docs forwarded from imported libraries.
57
+ * `Telo.Abstract`, and `Telo.Import` docs forwarded from imported libraries
58
+ * (plus their `exports.resources` instances) via `selectModuleManifestsForAnalysis`.
9
59
  * Stamps three flavours of metadata along the way:
10
60
  *
11
61
  * - `metadata.source` and `metadata.sourceLine` — already on each manifest
@@ -24,8 +74,7 @@ import { isModuleKind } from "./module-kinds.js";
24
74
  export function flattenForAnalyzer(graph: LoadedGraph): ResourceManifest[] {
25
75
  const result: ResourceManifest[] = [];
26
76
 
27
- const stampedEntry = collectModuleManifests(graph.entry);
28
- result.push(...stampedEntry);
77
+ result.push(...selectModuleManifestsForAnalysis(collectModuleManifests(graph.entry), true));
29
78
 
30
79
  const seen = new Set<string>([graph.rootSource]);
31
80
  const queue: string[] = [graph.rootSource];
@@ -43,36 +92,7 @@ export function flattenForAnalyzer(graph: LoadedGraph): ResourceManifest[] {
43
92
  const targetModule = graph.modules.get(edge.targetSource);
44
93
  if (!targetModule) continue;
45
94
 
46
- const stamped = collectModuleManifests(targetModule);
47
- const libDoc = stamped.find((m) => isModuleKind(m.kind));
48
- const exportedResources = new Set<string>(
49
- (libDoc as { exports?: { resources?: string[] } } | undefined)?.exports?.resources ?? [],
50
- );
51
- for (const m of stamped) {
52
- if (
53
- m.kind === "Telo.Definition" ||
54
- m.kind === "Telo.Abstract" ||
55
- m.kind === "Telo.Import"
56
- ) {
57
- result.push(m);
58
- } else if (
59
- !isModuleKind(m.kind) &&
60
- typeof m.metadata?.name === "string" &&
61
- exportedResources.has(m.metadata.name as string)
62
- ) {
63
- // Forward instances listed in the library's `exports.resources` so the
64
- // consumer's analyzer can resolve, gate, kind-check, and draw topology edges
65
- // for cross-module `!ref Alias.name`. The gate IS this forwarding — only
66
- // exported names cross the boundary. `metadata.forwardedExport` marks them as
67
- // cross-module resolution targets only (keyed by `metadata.module`), so ref
68
- // resolution / validation treats them as targets, never as local sources to
69
- // re-validate or walk.
70
- result.push({
71
- ...m,
72
- metadata: { ...m.metadata, forwardedExport: true } as ResourceManifest["metadata"],
73
- });
74
- }
75
- }
95
+ result.push(...selectModuleManifestsForAnalysis(collectModuleManifests(targetModule), false));
76
96
  }
77
97
  }
78
98
 
package/src/index.ts CHANGED
@@ -8,7 +8,11 @@ export type {
8
8
  LoadedModule,
9
9
  ParseError,
10
10
  } from "./loaded-types.js";
11
- export { flattenForAnalyzer, flattenLoadedModule } from "./flatten-for-analyzer.js";
11
+ export {
12
+ flattenForAnalyzer,
13
+ flattenLoadedModule,
14
+ selectModuleManifestsForAnalysis,
15
+ } from "./flatten-for-analyzer.js";
12
16
  export { visitManifest } from "./manifest-visitor.js";
13
17
  export type {
14
18
  CelSiteEvent,