@lucern/pack-host 0.1.0-alpha.2

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.
Files changed (104) hide show
  1. package/README.md +64 -0
  2. package/dist/contracts.d.ts +77 -0
  3. package/dist/contracts.js +21 -0
  4. package/dist/contracts.js.map +1 -0
  5. package/dist/convex.config.d.ts +5 -0
  6. package/dist/convex.config.js +9 -0
  7. package/dist/convex.config.js.map +1 -0
  8. package/dist/dependencyResolution.d.ts +18 -0
  9. package/dist/dependencyResolution.js +131 -0
  10. package/dist/dependencyResolution.js.map +1 -0
  11. package/dist/domain-pack/authoring.d.ts +172 -0
  12. package/dist/domain-pack/authoring.js +1896 -0
  13. package/dist/domain-pack/authoring.js.map +1 -0
  14. package/dist/domain-pack/contracts.d.ts +183 -0
  15. package/dist/domain-pack/contracts.js +65 -0
  16. package/dist/domain-pack/contracts.js.map +1 -0
  17. package/dist/domain-pack/index.d.ts +8 -0
  18. package/dist/domain-pack/index.js +3813 -0
  19. package/dist/domain-pack/index.js.map +1 -0
  20. package/dist/domain-pack/ontology/software-entities-v1.d.ts +102 -0
  21. package/dist/domain-pack/ontology/software-entities-v1.js +104 -0
  22. package/dist/domain-pack/ontology/software-entities-v1.js.map +1 -0
  23. package/dist/domain-pack/packs/developer-reasoning.d.ts +14 -0
  24. package/dist/domain-pack/packs/developer-reasoning.js +339 -0
  25. package/dist/domain-pack/packs/developer-reasoning.js.map +1 -0
  26. package/dist/domain-pack/packs/engineering-accelerator.d.ts +11 -0
  27. package/dist/domain-pack/packs/engineering-accelerator.js +1348 -0
  28. package/dist/domain-pack/packs/engineering-accelerator.js.map +1 -0
  29. package/dist/domain-pack/packs/index.d.ts +18 -0
  30. package/dist/domain-pack/packs/index.js +2653 -0
  31. package/dist/domain-pack/packs/index.js.map +1 -0
  32. package/dist/domain-pack/shaping.d.ts +54 -0
  33. package/dist/domain-pack/shaping.js +1013 -0
  34. package/dist/domain-pack/shaping.js.map +1 -0
  35. package/dist/domain-pack/validation.d.ts +26 -0
  36. package/dist/domain-pack/validation.js +775 -0
  37. package/dist/domain-pack/validation.js.map +1 -0
  38. package/dist/domain-pack.d.ts +8 -0
  39. package/dist/domain-pack.js +3813 -0
  40. package/dist/domain-pack.js.map +1 -0
  41. package/dist/index.d.ts +29 -0
  42. package/dist/index.js +5520 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/lifecycle.d.ts +27 -0
  45. package/dist/lifecycle.js +98 -0
  46. package/dist/lifecycle.js.map +1 -0
  47. package/dist/manifestValidation.d.ts +28 -0
  48. package/dist/manifestValidation.js +253 -0
  49. package/dist/manifestValidation.js.map +1 -0
  50. package/dist/manifests/chat-v1.d.ts +10 -0
  51. package/dist/manifests/chat-v1.js +87 -0
  52. package/dist/manifests/chat-v1.js.map +1 -0
  53. package/dist/manifests/deals-v1.d.ts +10 -0
  54. package/dist/manifests/deals-v1.js +107 -0
  55. package/dist/manifests/deals-v1.js.map +1 -0
  56. package/dist/manifests/decisions-v1.d.ts +10 -0
  57. package/dist/manifests/decisions-v1.js +103 -0
  58. package/dist/manifests/decisions-v1.js.map +1 -0
  59. package/dist/manifests/documents-v1.d.ts +10 -0
  60. package/dist/manifests/documents-v1.js +88 -0
  61. package/dist/manifests/documents-v1.js.map +1 -0
  62. package/dist/manifests/epistemic-algorithms-v1.d.ts +10 -0
  63. package/dist/manifests/epistemic-algorithms-v1.js +107 -0
  64. package/dist/manifests/epistemic-algorithms-v1.js.map +1 -0
  65. package/dist/manifests/graph-visualization-v1.d.ts +10 -0
  66. package/dist/manifests/graph-visualization-v1.js +88 -0
  67. package/dist/manifests/graph-visualization-v1.js.map +1 -0
  68. package/dist/manifests/index.d.ts +23 -0
  69. package/dist/manifests/index.js +955 -0
  70. package/dist/manifests/index.js.map +1 -0
  71. package/dist/manifests/news-v1.d.ts +10 -0
  72. package/dist/manifests/news-v1.js +93 -0
  73. package/dist/manifests/news-v1.js.map +1 -0
  74. package/dist/manifests/philosophy-mode-v1.d.ts +10 -0
  75. package/dist/manifests/philosophy-mode-v1.js +100 -0
  76. package/dist/manifests/philosophy-mode-v1.js.map +1 -0
  77. package/dist/manifests/task-management-v1.d.ts +10 -0
  78. package/dist/manifests/task-management-v1.js +86 -0
  79. package/dist/manifests/task-management-v1.js.map +1 -0
  80. package/dist/manifests/team-analysis-v1.d.ts +10 -0
  81. package/dist/manifests/team-analysis-v1.js +93 -0
  82. package/dist/manifests/team-analysis-v1.js.map +1 -0
  83. package/dist/manifests/themes-v1.d.ts +10 -0
  84. package/dist/manifests/themes-v1.js +118 -0
  85. package/dist/manifests/themes-v1.js.map +1 -0
  86. package/dist/manifests/user-profiles-v1.d.ts +10 -0
  87. package/dist/manifests/user-profiles-v1.js +100 -0
  88. package/dist/manifests/user-profiles-v1.js.map +1 -0
  89. package/dist/manifests.d.ts +14 -0
  90. package/dist/manifests.js +955 -0
  91. package/dist/manifests.js.map +1 -0
  92. package/dist/namespacePolicy.d.ts +26 -0
  93. package/dist/namespacePolicy.js +129 -0
  94. package/dist/namespacePolicy.js.map +1 -0
  95. package/dist/registry.d.ts +13 -0
  96. package/dist/registry.js +1710 -0
  97. package/dist/registry.js.map +1 -0
  98. package/dist/runtime.d.ts +19 -0
  99. package/dist/runtime.js +638 -0
  100. package/dist/runtime.js.map +1 -0
  101. package/dist/serviceContracts.d.ts +18 -0
  102. package/dist/serviceContracts.js +64 -0
  103. package/dist/serviceContracts.js.map +1 -0
  104. package/package.json +48 -0
@@ -0,0 +1,638 @@
1
+ import { z } from 'zod';
2
+
3
+ // src/dependencyResolution.ts
4
+ function toIssue(code, message, path, severity = "error") {
5
+ return {
6
+ code,
7
+ severity,
8
+ message,
9
+ path
10
+ };
11
+ }
12
+ function buildManifestMap(manifests) {
13
+ return new Map(manifests.map((manifest) => [manifest.key, manifest]));
14
+ }
15
+ function walkDependencyClosure(manifestKey, manifestsByKey, path, closure, issues) {
16
+ const manifest = manifestsByKey.get(manifestKey);
17
+ if (!manifest) {
18
+ return;
19
+ }
20
+ for (const dependency of manifest.dependencies) {
21
+ if (!manifestsByKey.has(dependency)) {
22
+ issues.push(
23
+ toIssue(
24
+ "PACK_DEPENDENCY_MISSING",
25
+ `Pack "${manifestKey}" depends on unknown pack "${dependency}".`,
26
+ `dependencies:${manifestKey}`
27
+ )
28
+ );
29
+ continue;
30
+ }
31
+ if (path.includes(dependency)) {
32
+ const cycle = [...path, dependency].join(" -> ");
33
+ issues.push(
34
+ toIssue(
35
+ "PACK_DEPENDENCY_CYCLE",
36
+ `Cycle detected: ${cycle}`,
37
+ `dependencies:${manifestKey}`
38
+ )
39
+ );
40
+ continue;
41
+ }
42
+ if (closure.has(dependency)) {
43
+ continue;
44
+ }
45
+ closure.add(dependency);
46
+ walkDependencyClosure(
47
+ dependency,
48
+ manifestsByKey,
49
+ [...path, dependency],
50
+ closure,
51
+ issues
52
+ );
53
+ }
54
+ }
55
+ function resolvePackDependencyGraph(manifests) {
56
+ const issues = [];
57
+ const manifestsByKey = buildManifestMap(manifests);
58
+ const indegree = /* @__PURE__ */ new Map();
59
+ const adjacency = /* @__PURE__ */ new Map();
60
+ for (const manifest of manifests) {
61
+ indegree.set(manifest.key, indegree.get(manifest.key) ?? 0);
62
+ adjacency.set(manifest.key, []);
63
+ }
64
+ for (const manifest of manifests) {
65
+ for (const dependency of manifest.dependencies) {
66
+ if (!manifestsByKey.has(dependency)) {
67
+ issues.push(
68
+ toIssue(
69
+ "PACK_DEPENDENCY_MISSING",
70
+ `Pack "${manifest.key}" depends on unknown pack "${dependency}".`,
71
+ `dependencies:${manifest.key}`
72
+ )
73
+ );
74
+ continue;
75
+ }
76
+ const dependencyDependents = adjacency.get(dependency) ?? [];
77
+ dependencyDependents.push(manifest.key);
78
+ adjacency.set(dependency, dependencyDependents);
79
+ indegree.set(manifest.key, (indegree.get(manifest.key) ?? 0) + 1);
80
+ }
81
+ }
82
+ const queue = [...indegree.entries()].filter(([, value]) => value === 0).map(([packKey]) => packKey).sort();
83
+ const orderedPackKeys = [];
84
+ while (queue.length > 0) {
85
+ const nextKey = queue.shift();
86
+ if (!nextKey) {
87
+ break;
88
+ }
89
+ orderedPackKeys.push(nextKey);
90
+ const dependents = adjacency.get(nextKey) ?? [];
91
+ for (const dependent of dependents) {
92
+ const current = indegree.get(dependent) ?? 0;
93
+ const updated = current - 1;
94
+ indegree.set(dependent, updated);
95
+ if (updated === 0) {
96
+ queue.push(dependent);
97
+ }
98
+ }
99
+ queue.sort();
100
+ }
101
+ if (orderedPackKeys.length !== manifestsByKey.size) {
102
+ const unresolved = [...indegree.entries()].filter(([, value]) => value > 0).map(([key]) => key).sort();
103
+ issues.push(
104
+ toIssue(
105
+ "PACK_DEPENDENCY_CYCLE",
106
+ `Dependency graph is not acyclic; unresolved packs: ${unresolved.join(", ")}`,
107
+ "dependencies"
108
+ )
109
+ );
110
+ }
111
+ const dependencyClosureByPack = {};
112
+ for (const manifest of manifests) {
113
+ const closure = /* @__PURE__ */ new Set();
114
+ walkDependencyClosure(
115
+ manifest.key,
116
+ manifestsByKey,
117
+ [manifest.key],
118
+ closure,
119
+ issues
120
+ );
121
+ dependencyClosureByPack[manifest.key] = [...closure].sort();
122
+ }
123
+ return {
124
+ orderedPackKeys,
125
+ dependencyClosureByPack,
126
+ issues,
127
+ valid: issues.every((issue) => issue.severity !== "error")
128
+ };
129
+ }
130
+ var manifestKeyPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*-v[0-9]+$/;
131
+ var semverPattern = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
132
+ var appPackManifestSchema = z.object({
133
+ key: z.string().regex(manifestKeyPattern),
134
+ name: z.string().min(1),
135
+ version: z.string().regex(semverPattern),
136
+ lifecycle: z.enum(["active", "beta", "experimental"]),
137
+ category: z.enum([
138
+ "conversation",
139
+ "research",
140
+ "graph",
141
+ "analytics",
142
+ "workflow",
143
+ "decision",
144
+ "news",
145
+ "documents",
146
+ "identity",
147
+ "operations",
148
+ "domain"
149
+ ]),
150
+ description: z.string().min(1),
151
+ dependencies: z.array(z.string().min(1)),
152
+ capabilityFlags: z.array(z.string().min(1)),
153
+ routeNamespace: z.object({
154
+ web: z.array(z.string().min(1)),
155
+ api: z.array(z.string().min(1))
156
+ }),
157
+ surfaces: z.object({
158
+ components: z.array(z.string().min(1)),
159
+ convex: z.array(z.string().min(1)),
160
+ tools: z.array(z.string().min(1))
161
+ }),
162
+ policyProfile: z.object({
163
+ audiences: z.array(z.string().min(1)).min(1),
164
+ rules: z.array(
165
+ z.object({
166
+ resource: z.enum([
167
+ "project",
168
+ "node",
169
+ "edge",
170
+ "artifact",
171
+ "report_section",
172
+ "tool_action",
173
+ "task",
174
+ "user_profile",
175
+ "team_analytics"
176
+ ]),
177
+ actions: z.array(z.enum(["read", "summarize", "export", "mutate", "admin"])).min(1),
178
+ notes: z.string().optional()
179
+ })
180
+ ).min(1)
181
+ }),
182
+ dataContract: z.object({
183
+ requiredNodeTypes: z.array(z.string().min(1)),
184
+ requiredEdgeTypes: z.array(z.string().min(1)),
185
+ requiredTables: z.array(z.string().min(1)).min(1),
186
+ projectionBehavior: z.enum([
187
+ "none",
188
+ "inherits_policy",
189
+ "projection_required"
190
+ ])
191
+ }),
192
+ templates: z.object({
193
+ workflows: z.array(z.string().min(1)),
194
+ prompts: z.array(z.string().min(1)),
195
+ reports: z.array(z.string().min(1)),
196
+ uiLabels: z.array(z.string().min(1))
197
+ }),
198
+ testSuite: z.object({
199
+ parity: z.array(z.string().min(1)).min(1),
200
+ policy: z.array(z.string().min(1)).min(1),
201
+ contract: z.array(z.string().min(1)).min(1)
202
+ }),
203
+ sharedServices: z.array(
204
+ z.object({
205
+ service: z.enum([
206
+ "decision-kernel",
207
+ "knowledge-compiler",
208
+ "learning-loop"
209
+ ]),
210
+ mode: z.enum(["required", "optional"]),
211
+ contracts: z.array(z.string().min(1)).min(1)
212
+ })
213
+ )
214
+ });
215
+ function toIssue2(code, message, path, severity = "error") {
216
+ return {
217
+ code,
218
+ severity,
219
+ message,
220
+ path
221
+ };
222
+ }
223
+ function collectDuplicateValues(values) {
224
+ const counts = /* @__PURE__ */ new Map();
225
+ for (const value of values) {
226
+ counts.set(value, (counts.get(value) ?? 0) + 1);
227
+ }
228
+ return [...counts.entries()].filter(([, count]) => count > 1).map(([value]) => value).sort();
229
+ }
230
+ function collectUnknownValues(values, knownValues) {
231
+ const known = new Set(knownValues);
232
+ return values.filter((value) => !known.has(value));
233
+ }
234
+ function validateManifestShape(manifest) {
235
+ const parsed = appPackManifestSchema.safeParse(manifest);
236
+ if (parsed.success) {
237
+ return [];
238
+ }
239
+ return parsed.error.issues.map(
240
+ (issue) => toIssue2(
241
+ "PACK_MANIFEST_SCHEMA_INVALID",
242
+ issue.message,
243
+ issue.path.join(".") || "(root)"
244
+ )
245
+ );
246
+ }
247
+ function validateManifestUniqueness(manifest) {
248
+ const issues = [];
249
+ const duplicateDependencies = collectDuplicateValues(manifest.dependencies);
250
+ if (duplicateDependencies.length > 0) {
251
+ issues.push(
252
+ toIssue2(
253
+ "PACK_DEPENDENCIES_DUPLICATE",
254
+ `Duplicate dependencies declared: ${duplicateDependencies.join(", ")}`,
255
+ "dependencies"
256
+ )
257
+ );
258
+ }
259
+ if (manifest.dependencies.includes(manifest.key)) {
260
+ issues.push(
261
+ toIssue2(
262
+ "PACK_DEPENDENCY_SELF_REFERENCE",
263
+ `Pack "${manifest.key}" cannot depend on itself.`,
264
+ "dependencies"
265
+ )
266
+ );
267
+ }
268
+ const duplicateCapabilities = collectDuplicateValues(
269
+ manifest.capabilityFlags
270
+ );
271
+ if (duplicateCapabilities.length > 0) {
272
+ issues.push(
273
+ toIssue2(
274
+ "PACK_CAPABILITIES_DUPLICATE",
275
+ `Duplicate capability flags declared: ${duplicateCapabilities.join(", ")}`,
276
+ "capabilityFlags"
277
+ )
278
+ );
279
+ }
280
+ const duplicateWebRoutes = collectDuplicateValues(
281
+ manifest.routeNamespace.web
282
+ );
283
+ if (duplicateWebRoutes.length > 0) {
284
+ issues.push(
285
+ toIssue2(
286
+ "PACK_WEB_ROUTES_DUPLICATE",
287
+ `Duplicate web routes declared: ${duplicateWebRoutes.join(", ")}`,
288
+ "routeNamespace.web"
289
+ )
290
+ );
291
+ }
292
+ const duplicateApiRoutes = collectDuplicateValues(
293
+ manifest.routeNamespace.api
294
+ );
295
+ if (duplicateApiRoutes.length > 0) {
296
+ issues.push(
297
+ toIssue2(
298
+ "PACK_API_ROUTES_DUPLICATE",
299
+ `Duplicate api routes declared: ${duplicateApiRoutes.join(", ")}`,
300
+ "routeNamespace.api"
301
+ )
302
+ );
303
+ }
304
+ const duplicateServices = collectDuplicateValues(
305
+ manifest.sharedServices.map((integration) => integration.service)
306
+ );
307
+ if (duplicateServices.length > 0) {
308
+ issues.push(
309
+ toIssue2(
310
+ "PACK_SHARED_SERVICE_DUPLICATE",
311
+ `Duplicate shared-service integrations declared: ${duplicateServices.join(", ")}`,
312
+ "sharedServices"
313
+ )
314
+ );
315
+ }
316
+ return issues;
317
+ }
318
+ function validateManifestDictionary(manifest, dictionary) {
319
+ if (!dictionary) {
320
+ return [];
321
+ }
322
+ const issues = [];
323
+ const unknownNodeTypes = collectUnknownValues(
324
+ manifest.dataContract.requiredNodeTypes,
325
+ dictionary.nodeTypes
326
+ );
327
+ const unknownEdgeTypes = collectUnknownValues(
328
+ manifest.dataContract.requiredEdgeTypes,
329
+ dictionary.edgeTypes
330
+ );
331
+ const unknownTables = collectUnknownValues(
332
+ manifest.dataContract.requiredTables,
333
+ dictionary.tables
334
+ );
335
+ if (unknownNodeTypes.length > 0) {
336
+ issues.push(
337
+ toIssue2(
338
+ "PACK_UNKNOWN_NODE_TYPES",
339
+ `Unknown required node types: ${unknownNodeTypes.join(", ")}`,
340
+ "dataContract.requiredNodeTypes"
341
+ )
342
+ );
343
+ }
344
+ if (unknownEdgeTypes.length > 0) {
345
+ issues.push(
346
+ toIssue2(
347
+ "PACK_UNKNOWN_EDGE_TYPES",
348
+ `Unknown required edge types: ${unknownEdgeTypes.join(", ")}`,
349
+ "dataContract.requiredEdgeTypes"
350
+ )
351
+ );
352
+ }
353
+ if (unknownTables.length > 0) {
354
+ issues.push(
355
+ toIssue2(
356
+ "PACK_UNKNOWN_TABLES",
357
+ `Unknown required tables: ${unknownTables.join(", ")}`,
358
+ "dataContract.requiredTables"
359
+ )
360
+ );
361
+ }
362
+ return issues;
363
+ }
364
+ function validateAppPackManifest(manifest, dictionary) {
365
+ const issues = [
366
+ ...validateManifestShape(manifest),
367
+ ...validateManifestUniqueness(manifest),
368
+ ...validateManifestDictionary(manifest, dictionary)
369
+ ];
370
+ return {
371
+ manifestKey: manifest.key,
372
+ valid: issues.every((issue) => issue.severity !== "error"),
373
+ issues
374
+ };
375
+ }
376
+
377
+ // src/namespacePolicy.ts
378
+ var PACK_NAMESPACE_COLLISION_ALLOWLIST = [
379
+ {
380
+ surface: "web",
381
+ namespace: "/(chat)/chat/[id]",
382
+ allowedPackKeys: ["chat-v1", "philosophy-mode-v1"],
383
+ rationale: "Philosophy mode extends the chat surface and intentionally shares the chat detail route."
384
+ },
385
+ {
386
+ surface: "web",
387
+ namespace: "/(projects)/projects",
388
+ allowedPackKeys: ["deals-v1", "themes-v1"],
389
+ rationale: "Deals and themes intentionally share the topic index shell mounted under the legacy /projects customer-zero shell."
390
+ },
391
+ {
392
+ surface: "web",
393
+ namespace: "/(projects)/projects/[projectId]",
394
+ allowedPackKeys: ["deals-v1", "themes-v1"],
395
+ rationale: "Deals and themes intentionally share topic detail shell routing while the outer customer-zero shell still uses legacy project path segments."
396
+ },
397
+ {
398
+ surface: "api",
399
+ namespace: "/api/philosophy/get-profile",
400
+ allowedPackKeys: ["philosophy-mode-v1", "user-profiles-v1"],
401
+ rationale: "User profiles and philosophy mode share profile retrieval endpoint for compatibility."
402
+ },
403
+ {
404
+ surface: "api",
405
+ namespace: "/api/research/*",
406
+ allowedPackKeys: ["deals-v1", "themes-v1"],
407
+ rationale: "Deals and themes share research API namespace until productized API gateway split."
408
+ },
409
+ {
410
+ surface: "api",
411
+ namespace: "/api/reports/*",
412
+ allowedPackKeys: ["deals-v1", "decisions-v1", "themes-v1"],
413
+ rationale: "Domain packs intentionally consume shared report compiler endpoints in the same namespace."
414
+ }
415
+ ];
416
+ function toIssue3(code, message, path, severity = "error") {
417
+ return {
418
+ code,
419
+ severity,
420
+ message,
421
+ path
422
+ };
423
+ }
424
+ function normalizeKeySet(values) {
425
+ return [...new Set(values)].sort().join("|");
426
+ }
427
+ function detectNamespaceCollisions(manifests) {
428
+ const collisions = [];
429
+ for (const surface of ["web", "api"]) {
430
+ const namespaceToPacks = /* @__PURE__ */ new Map();
431
+ for (const manifest of manifests) {
432
+ const namespaces = manifest.routeNamespace[surface];
433
+ for (const namespace of namespaces) {
434
+ const existing = namespaceToPacks.get(namespace) ?? [];
435
+ existing.push(manifest.key);
436
+ namespaceToPacks.set(namespace, existing);
437
+ }
438
+ }
439
+ for (const [namespace, packKeys] of namespaceToPacks.entries()) {
440
+ if (packKeys.length <= 1) {
441
+ continue;
442
+ }
443
+ collisions.push({
444
+ surface,
445
+ namespace,
446
+ packKeys: [...new Set(packKeys)].sort()
447
+ });
448
+ }
449
+ }
450
+ return collisions.sort((left, right) => {
451
+ if (left.surface !== right.surface) {
452
+ return left.surface.localeCompare(right.surface);
453
+ }
454
+ return left.namespace.localeCompare(right.namespace);
455
+ });
456
+ }
457
+ function validatePackNamespacePolicies(manifests) {
458
+ const issues = [];
459
+ const collisions = detectNamespaceCollisions(manifests);
460
+ const allowlistByKey = /* @__PURE__ */ new Map();
461
+ for (const entry of PACK_NAMESPACE_COLLISION_ALLOWLIST) {
462
+ const key = `${entry.surface}:${entry.namespace}`;
463
+ if (allowlistByKey.has(key)) {
464
+ issues.push(
465
+ toIssue3(
466
+ "PACK_NAMESPACE_ALLOWLIST_DUPLICATE",
467
+ `Duplicate allowlist entry for ${key}.`,
468
+ "namespacePolicy.allowlist"
469
+ )
470
+ );
471
+ continue;
472
+ }
473
+ allowlistByKey.set(key, entry);
474
+ }
475
+ for (const collision of collisions) {
476
+ const key = `${collision.surface}:${collision.namespace}`;
477
+ const allowlistEntry = allowlistByKey.get(key);
478
+ if (!allowlistEntry) {
479
+ issues.push(
480
+ toIssue3(
481
+ "PACK_NAMESPACE_COLLISION_UNAPPROVED",
482
+ `Unapproved ${collision.surface} namespace collision for "${collision.namespace}" across packs: ${collision.packKeys.join(", ")}`,
483
+ `namespacePolicy.${collision.surface}`
484
+ )
485
+ );
486
+ continue;
487
+ }
488
+ const collidedSet = normalizeKeySet(collision.packKeys);
489
+ const allowedSet = normalizeKeySet(allowlistEntry.allowedPackKeys);
490
+ if (collidedSet !== allowedSet) {
491
+ issues.push(
492
+ toIssue3(
493
+ "PACK_NAMESPACE_COLLISION_MISMATCH",
494
+ `Collision set mismatch for "${collision.namespace}". collided=${collidedSet} allowlist=${allowedSet}`,
495
+ `namespacePolicy.${collision.surface}`
496
+ )
497
+ );
498
+ }
499
+ }
500
+ return issues;
501
+ }
502
+
503
+ // src/serviceContracts.ts
504
+ function hasSharedService(manifest, service) {
505
+ return manifest.sharedServices.some(
506
+ (integration) => integration.service === service
507
+ );
508
+ }
509
+ function hasDecisionIntegrationSignals(manifest) {
510
+ if (manifest.category === "decision") {
511
+ return true;
512
+ }
513
+ return manifest.capabilityFlags.some(
514
+ (flag) => flag.startsWith("decision.") || flag.includes("decision.integration")
515
+ );
516
+ }
517
+ function hasReportIntegrationSignals(manifest) {
518
+ if (manifest.templates.reports.length > 0) {
519
+ return true;
520
+ }
521
+ return manifest.routeNamespace.api.some(
522
+ (namespace) => namespace.includes("/api/reports")
523
+ );
524
+ }
525
+ function hasLearningIntegrationSignals(manifest) {
526
+ return manifest.capabilityFlags.some(
527
+ (flag) => flag.startsWith("learning.") || flag.includes("policy.injection") || flag.includes("adaptive-learning")
528
+ );
529
+ }
530
+ function validatePackSharedServiceContracts(manifests) {
531
+ const issues = [];
532
+ for (const manifest of manifests) {
533
+ if (hasReportIntegrationSignals(manifest) && !hasSharedService(manifest, "knowledge-compiler")) {
534
+ issues.push({
535
+ packKey: manifest.key,
536
+ service: "knowledge-compiler",
537
+ severity: "error",
538
+ code: "PACK_REPORT_SERVICE_MISSING",
539
+ message: "Pack declares report outputs/routes but is missing knowledge-compiler shared service integration."
540
+ });
541
+ }
542
+ if (hasDecisionIntegrationSignals(manifest) && !hasSharedService(manifest, "decision-kernel")) {
543
+ issues.push({
544
+ packKey: manifest.key,
545
+ service: "decision-kernel",
546
+ severity: "error",
547
+ code: "PACK_DECISION_SERVICE_MISSING",
548
+ message: "Pack declares decision behavior but is missing decision-kernel shared service integration."
549
+ });
550
+ }
551
+ if (hasLearningIntegrationSignals(manifest) && !hasSharedService(manifest, "learning-loop")) {
552
+ issues.push({
553
+ packKey: manifest.key,
554
+ service: "learning-loop",
555
+ severity: "error",
556
+ code: "PACK_LEARNING_SERVICE_MISSING",
557
+ message: "Pack declares adaptive learning behavior but is missing learning-loop shared service integration."
558
+ });
559
+ }
560
+ }
561
+ return issues;
562
+ }
563
+
564
+ // src/runtime.ts
565
+ function toIssue4(code, message, path, severity = "error") {
566
+ return {
567
+ code,
568
+ severity,
569
+ message,
570
+ path
571
+ };
572
+ }
573
+ function validateRegistryIdentity(manifests) {
574
+ const issues = [];
575
+ const keyCounts = /* @__PURE__ */ new Map();
576
+ const identityCounts = /* @__PURE__ */ new Map();
577
+ for (const manifest of manifests) {
578
+ keyCounts.set(manifest.key, (keyCounts.get(manifest.key) ?? 0) + 1);
579
+ const identity = `${manifest.key}@${manifest.version}`;
580
+ identityCounts.set(identity, (identityCounts.get(identity) ?? 0) + 1);
581
+ }
582
+ for (const [key, count] of keyCounts.entries()) {
583
+ if (count > 1) {
584
+ issues.push(
585
+ toIssue4(
586
+ "PACK_KEY_DUPLICATE",
587
+ `Duplicate pack key registered: ${key}`,
588
+ "registry.keys"
589
+ )
590
+ );
591
+ }
592
+ }
593
+ for (const [identity, count] of identityCounts.entries()) {
594
+ if (count > 1) {
595
+ issues.push(
596
+ toIssue4(
597
+ "PACK_VERSION_DUPLICATE",
598
+ `Duplicate pack identity registered: ${identity}`,
599
+ "registry.versions"
600
+ )
601
+ );
602
+ }
603
+ }
604
+ return issues;
605
+ }
606
+ function validatePackRegistry(manifests, dictionary) {
607
+ const manifestResults = manifests.map(
608
+ (manifest) => validateAppPackManifest(manifest, dictionary)
609
+ );
610
+ const dependencyResult = resolvePackDependencyGraph(manifests);
611
+ const sharedServiceIssues = validatePackSharedServiceContracts(manifests).map(
612
+ (issue) => toIssue4(
613
+ issue.code,
614
+ `[${issue.packKey}] ${issue.message}`,
615
+ `sharedServices:${issue.packKey}`,
616
+ issue.severity
617
+ )
618
+ );
619
+ const namespaceIssues = validatePackNamespacePolicies(manifests);
620
+ const issues = [
621
+ ...validateRegistryIdentity(manifests),
622
+ ...manifestResults.flatMap((result) => result.issues),
623
+ ...dependencyResult.issues,
624
+ ...sharedServiceIssues,
625
+ ...namespaceIssues
626
+ ];
627
+ return {
628
+ valid: issues.every((issue) => issue.severity !== "error"),
629
+ manifestResults,
630
+ dependencyOrder: dependencyResult.orderedPackKeys,
631
+ dependencyClosureByPack: dependencyResult.dependencyClosureByPack,
632
+ issues
633
+ };
634
+ }
635
+
636
+ export { validatePackRegistry };
637
+ //# sourceMappingURL=runtime.js.map
638
+ //# sourceMappingURL=runtime.js.map