@lucern/pack-host 1.0.28 → 1.0.30

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 (67) hide show
  1. package/dist/contracts.d.ts +35 -35
  2. package/dist/contracts.js.map +1 -1
  3. package/dist/dependencyResolution.d.ts +3 -3
  4. package/dist/dependencyResolution.js +83 -59
  5. package/dist/dependencyResolution.js.map +1 -1
  6. package/dist/domain-pack/authoring.core.d.ts +82 -82
  7. package/dist/domain-pack/authoring.core.js +7 -6
  8. package/dist/domain-pack/authoring.core.js.map +1 -1
  9. package/dist/domain-pack/authoring.js +400 -281
  10. package/dist/domain-pack/authoring.js.map +1 -1
  11. package/dist/domain-pack/authoring.validation.js +400 -281
  12. package/dist/domain-pack/authoring.validation.js.map +1 -1
  13. package/dist/domain-pack/contracts.d.ts +95 -95
  14. package/dist/domain-pack/contracts.js.map +1 -1
  15. package/dist/domain-pack/index.js +416 -285
  16. package/dist/domain-pack/index.js.map +1 -1
  17. package/dist/domain-pack/ontology/software-entities-v1.d.ts +7 -7
  18. package/dist/domain-pack/ontology/software-entities-v1.js.map +1 -1
  19. package/dist/domain-pack/packs/developer-reasoning.js +7 -1
  20. package/dist/domain-pack/packs/developer-reasoning.js.map +1 -1
  21. package/dist/domain-pack/packs/engineering-accelerator.js.map +1 -1
  22. package/dist/domain-pack/packs/index.js +333 -239
  23. package/dist/domain-pack/packs/index.js.map +1 -1
  24. package/dist/domain-pack/shaping.d.ts +15 -15
  25. package/dist/domain-pack/shaping.js +326 -238
  26. package/dist/domain-pack/shaping.js.map +1 -1
  27. package/dist/domain-pack/validation.d.ts +6 -6
  28. package/dist/domain-pack/validation.js +318 -236
  29. package/dist/domain-pack/validation.js.map +1 -1
  30. package/dist/domain-pack.js +416 -285
  31. package/dist/domain-pack.js.map +1 -1
  32. package/dist/index.d.ts +6 -6
  33. package/dist/index.js +3793 -3643
  34. package/dist/index.js.map +1 -1
  35. package/dist/lifecycle.d.ts +9 -9
  36. package/dist/lifecycle.js.map +1 -1
  37. package/dist/manifestValidation.d.ts +9 -9
  38. package/dist/manifestValidation.js.map +1 -1
  39. package/dist/manifests/chat-v1.js.map +1 -1
  40. package/dist/manifests/deals-v1.js +1 -6
  41. package/dist/manifests/deals-v1.js.map +1 -1
  42. package/dist/manifests/decisions-v1.js.map +1 -1
  43. package/dist/manifests/documents-v1.js.map +1 -1
  44. package/dist/manifests/epistemic-algorithms-v1.js.map +1 -1
  45. package/dist/manifests/graph-visualization-v1.js.map +1 -1
  46. package/dist/manifests/index.js +1 -6
  47. package/dist/manifests/index.js.map +1 -1
  48. package/dist/manifests/news-v1.js.map +1 -1
  49. package/dist/manifests/philosophy-mode-v1.js.map +1 -1
  50. package/dist/manifests/sprints-v1.js.map +1 -1
  51. package/dist/manifests/task-management-v1.js.map +1 -1
  52. package/dist/manifests/team-analysis-v1.js.map +1 -1
  53. package/dist/manifests/themes-v1.js.map +1 -1
  54. package/dist/manifests/user-profiles-v1.js.map +1 -1
  55. package/dist/manifests.js +1 -6
  56. package/dist/manifests.js.map +1 -1
  57. package/dist/namespacePolicy.d.ts +6 -6
  58. package/dist/namespacePolicy.js.map +1 -1
  59. package/dist/proof-attestation.json +1 -1
  60. package/dist/registry.js +84 -65
  61. package/dist/registry.js.map +1 -1
  62. package/dist/runtime.d.ts +6 -6
  63. package/dist/runtime.js +83 -59
  64. package/dist/runtime.js.map +1 -1
  65. package/dist/serviceContracts.d.ts +4 -4
  66. package/dist/serviceContracts.js.map +1 -1
  67. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/namespacePolicy.ts"],"names":[],"mappings":"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","file":"namespacePolicy.js","sourcesContent":["/**\n * Pack Namespace Collision Policy\n *\n * Enforces explicit allowlisting for cross-pack route namespace sharing.\n */\n\nimport type { AppPackManifest } from \"./contracts\";\nimport type { PackValidationIssue } from \"./manifestValidation\";\n\nexport type NamespaceSurface = \"web\" | \"api\";\n\nexport type NamespaceCollision = {\n surface: NamespaceSurface;\n namespace: string;\n packKeys: string[];\n};\n\nexport type NamespaceCollisionAllowlistEntry = {\n surface: NamespaceSurface;\n namespace: string;\n allowedPackKeys: string[];\n rationale: string;\n};\n\nexport const PACK_NAMESPACE_COLLISION_ALLOWLIST: NamespaceCollisionAllowlistEntry[] =\n [\n {\n surface: \"web\",\n namespace: \"/(chat)/chat/[id]\",\n allowedPackKeys: [\"chat-v1\", \"philosophy-mode-v1\"],\n rationale:\n \"Philosophy mode extends the chat surface and intentionally shares the chat detail route.\",\n },\n {\n surface: \"web\",\n namespace: \"/(projects)/projects\",\n allowedPackKeys: [\"deals-v1\", \"themes-v1\"],\n rationale:\n \"Deals and themes intentionally share the topic index shell mounted under the legacy /projects customer-zero shell.\",\n },\n {\n surface: \"web\",\n namespace: \"/(projects)/projects/[projectId]\",\n allowedPackKeys: [\"deals-v1\", \"themes-v1\"],\n rationale:\n \"Deals and themes intentionally share topic detail shell routing while the outer customer-zero shell still uses legacy project path segments.\",\n },\n {\n surface: \"api\",\n namespace: \"/api/philosophy/get-profile\",\n allowedPackKeys: [\"philosophy-mode-v1\", \"user-profiles-v1\"],\n rationale:\n \"User profiles and philosophy mode share profile retrieval endpoint for compatibility.\",\n },\n {\n surface: \"api\",\n namespace: \"/api/research/*\",\n allowedPackKeys: [\"deals-v1\", \"themes-v1\"],\n rationale:\n \"Deals and themes share research API namespace until productized API gateway split.\",\n },\n {\n surface: \"api\",\n namespace: \"/api/reports/*\",\n allowedPackKeys: [\"deals-v1\", \"decisions-v1\", \"themes-v1\"],\n rationale:\n \"Domain packs intentionally consume shared report compiler endpoints in the same namespace.\",\n },\n ];\n\nfunction toIssue(\n code: string,\n message: string,\n path: string,\n severity: \"error\" | \"warning\" = \"error\"\n): PackValidationIssue {\n return {\n code,\n severity,\n message,\n path,\n };\n}\n\nfunction normalizeKeySet(values: string[]): string {\n return [...new Set(values)].sort().join(\"|\");\n}\n\nexport function detectNamespaceCollisions(\n manifests: AppPackManifest[]\n): NamespaceCollision[] {\n const collisions: NamespaceCollision[] = [];\n\n for (const surface of [\"web\", \"api\"] as const) {\n const namespaceToPacks = new Map<string, string[]>();\n for (const manifest of manifests) {\n const namespaces = manifest.routeNamespace[surface];\n for (const namespace of namespaces) {\n const existing = namespaceToPacks.get(namespace) ?? [];\n existing.push(manifest.key);\n namespaceToPacks.set(namespace, existing);\n }\n }\n\n for (const [namespace, packKeys] of namespaceToPacks.entries()) {\n if (packKeys.length <= 1) {\n continue;\n }\n collisions.push({\n surface,\n namespace,\n packKeys: [...new Set(packKeys)].sort(),\n });\n }\n }\n\n return collisions.sort((left, right) => {\n if (left.surface !== right.surface) {\n return left.surface.localeCompare(right.surface);\n }\n return left.namespace.localeCompare(right.namespace);\n });\n}\n\nexport function validatePackNamespacePolicies(\n manifests: AppPackManifest[]\n): PackValidationIssue[] {\n const issues: PackValidationIssue[] = [];\n const collisions = detectNamespaceCollisions(manifests);\n const allowlistByKey = new Map<string, NamespaceCollisionAllowlistEntry>();\n\n for (const entry of PACK_NAMESPACE_COLLISION_ALLOWLIST) {\n const key = `${entry.surface}:${entry.namespace}`;\n if (allowlistByKey.has(key)) {\n issues.push(\n toIssue(\n \"PACK_NAMESPACE_ALLOWLIST_DUPLICATE\",\n `Duplicate allowlist entry for ${key}.`,\n \"namespacePolicy.allowlist\"\n )\n );\n continue;\n }\n allowlistByKey.set(key, entry);\n }\n\n for (const collision of collisions) {\n const key = `${collision.surface}:${collision.namespace}`;\n const allowlistEntry = allowlistByKey.get(key);\n if (!allowlistEntry) {\n issues.push(\n toIssue(\n \"PACK_NAMESPACE_COLLISION_UNAPPROVED\",\n `Unapproved ${collision.surface} namespace collision for \"${collision.namespace}\" across packs: ${collision.packKeys.join(\", \")}`,\n `namespacePolicy.${collision.surface}`\n )\n );\n continue;\n }\n\n const collidedSet = normalizeKeySet(collision.packKeys);\n const allowedSet = normalizeKeySet(allowlistEntry.allowedPackKeys);\n if (collidedSet !== allowedSet) {\n issues.push(\n toIssue(\n \"PACK_NAMESPACE_COLLISION_MISMATCH\",\n `Collision set mismatch for \"${collision.namespace}\". collided=${collidedSet} allowlist=${allowedSet}`,\n `namespacePolicy.${collision.surface}`\n )\n );\n }\n }\n\n return issues;\n}\n"]}
1
+ {"version":3,"sources":["../src/namespacePolicy.ts"],"names":[],"mappings":"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","file":"namespacePolicy.js","sourcesContent":["// biome-ignore-all lint/style/useFilenamingConvention: Legacy public @lucern/pack-host/namespacePolicy subpath.\n/**\n * Pack Namespace Collision Policy\n *\n * Enforces explicit allowlisting for cross-pack route namespace sharing.\n */\n\nimport type { AppPackManifest } from \"./contracts\";\nimport type { PackValidationIssue } from \"./manifestValidation\";\n\nexport type NamespaceSurface = \"web\" | \"api\";\n\nexport interface NamespaceCollision {\n namespace: string;\n packKeys: string[];\n surface: NamespaceSurface;\n}\n\nexport interface NamespaceCollisionAllowlistEntry {\n allowedPackKeys: string[];\n namespace: string;\n rationale: string;\n surface: NamespaceSurface;\n}\n\nexport const PACK_NAMESPACE_COLLISION_ALLOWLIST: NamespaceCollisionAllowlistEntry[] =\n [\n {\n surface: \"web\",\n namespace: \"/(chat)/chat/[id]\",\n allowedPackKeys: [\"chat-v1\", \"philosophy-mode-v1\"],\n rationale:\n \"Philosophy mode extends the chat surface and intentionally shares the chat detail route.\",\n },\n {\n surface: \"web\",\n namespace: \"/(projects)/projects\",\n allowedPackKeys: [\"deals-v1\", \"themes-v1\"],\n rationale:\n \"Deals and themes intentionally share the topic index shell mounted under the legacy /projects customer-zero shell.\",\n },\n {\n surface: \"web\",\n namespace: \"/(projects)/projects/[projectId]\",\n allowedPackKeys: [\"deals-v1\", \"themes-v1\"],\n rationale:\n \"Deals and themes intentionally share topic detail shell routing while the outer customer-zero shell still uses legacy project path segments.\",\n },\n {\n surface: \"api\",\n namespace: \"/api/philosophy/get-profile\",\n allowedPackKeys: [\"philosophy-mode-v1\", \"user-profiles-v1\"],\n rationale:\n \"User profiles and philosophy mode share profile retrieval endpoint for compatibility.\",\n },\n {\n surface: \"api\",\n namespace: \"/api/research/*\",\n allowedPackKeys: [\"deals-v1\", \"themes-v1\"],\n rationale:\n \"Deals and themes share research API namespace until productized API gateway split.\",\n },\n {\n surface: \"api\",\n namespace: \"/api/reports/*\",\n allowedPackKeys: [\"deals-v1\", \"decisions-v1\", \"themes-v1\"],\n rationale:\n \"Domain packs intentionally consume shared report compiler endpoints in the same namespace.\",\n },\n ];\n\nfunction toIssue(\n code: string,\n message: string,\n path: string,\n severity: \"error\" | \"warning\" = \"error\"\n): PackValidationIssue {\n return {\n code,\n severity,\n message,\n path,\n };\n}\n\nfunction normalizeKeySet(values: string[]): string {\n return [...new Set(values)].sort().join(\"|\");\n}\n\nexport function detectNamespaceCollisions(\n manifests: AppPackManifest[]\n): NamespaceCollision[] {\n const collisions: NamespaceCollision[] = [];\n\n for (const surface of [\"web\", \"api\"] as const) {\n const namespaceToPacks = new Map<string, string[]>();\n for (const manifest of manifests) {\n const namespaces = manifest.routeNamespace[surface];\n for (const namespace of namespaces) {\n const existing = namespaceToPacks.get(namespace) ?? [];\n existing.push(manifest.key);\n namespaceToPacks.set(namespace, existing);\n }\n }\n\n for (const [namespace, packKeys] of namespaceToPacks.entries()) {\n if (packKeys.length <= 1) {\n continue;\n }\n collisions.push({\n surface,\n namespace,\n packKeys: [...new Set(packKeys)].sort(),\n });\n }\n }\n\n return collisions.sort((left, right) => {\n if (left.surface !== right.surface) {\n return left.surface.localeCompare(right.surface);\n }\n return left.namespace.localeCompare(right.namespace);\n });\n}\n\nexport function validatePackNamespacePolicies(\n manifests: AppPackManifest[]\n): PackValidationIssue[] {\n const issues: PackValidationIssue[] = [];\n const collisions = detectNamespaceCollisions(manifests);\n const allowlistByKey = new Map<string, NamespaceCollisionAllowlistEntry>();\n\n for (const entry of PACK_NAMESPACE_COLLISION_ALLOWLIST) {\n const key = `${entry.surface}:${entry.namespace}`;\n if (allowlistByKey.has(key)) {\n issues.push(\n toIssue(\n \"PACK_NAMESPACE_ALLOWLIST_DUPLICATE\",\n `Duplicate allowlist entry for ${key}.`,\n \"namespacePolicy.allowlist\"\n )\n );\n continue;\n }\n allowlistByKey.set(key, entry);\n }\n\n for (const collision of collisions) {\n const key = `${collision.surface}:${collision.namespace}`;\n const allowlistEntry = allowlistByKey.get(key);\n if (!allowlistEntry) {\n issues.push(\n toIssue(\n \"PACK_NAMESPACE_COLLISION_UNAPPROVED\",\n `Unapproved ${collision.surface} namespace collision for \"${collision.namespace}\" across packs: ${collision.packKeys.join(\", \")}`,\n `namespacePolicy.${collision.surface}`\n )\n );\n continue;\n }\n\n const collidedSet = normalizeKeySet(collision.packKeys);\n const allowedSet = normalizeKeySet(allowlistEntry.allowedPackKeys);\n if (collidedSet !== allowedSet) {\n issues.push(\n toIssue(\n \"PACK_NAMESPACE_COLLISION_MISMATCH\",\n `Collision set mismatch for \"${collision.namespace}\". collided=${collidedSet} allowlist=${allowedSet}`,\n `namespacePolicy.${collision.surface}`\n )\n );\n }\n }\n\n return issues;\n}\n"]}
@@ -41,5 +41,5 @@
41
41
  "convex-validators",
42
42
  "proof-attestation"
43
43
  ],
44
- "signedAt": 1781456839725
44
+ "signedAt": 1782180087025
45
45
  }
package/dist/registry.js CHANGED
@@ -12,6 +12,73 @@ function toIssue(code, message, path, severity = "error") {
12
12
  function buildManifestMap(manifests) {
13
13
  return new Map(manifests.map((manifest) => [manifest.key, manifest]));
14
14
  }
15
+ function initializeDependencyGraph(manifests) {
16
+ const manifestsByKey = buildManifestMap(manifests);
17
+ const indegree = /* @__PURE__ */ new Map();
18
+ const adjacency = /* @__PURE__ */ new Map();
19
+ for (const manifest of manifests) {
20
+ indegree.set(manifest.key, indegree.get(manifest.key) ?? 0);
21
+ adjacency.set(manifest.key, []);
22
+ }
23
+ return { adjacency, indegree, manifestsByKey };
24
+ }
25
+ function linkPackDependency(manifest, dependency, graph, issues) {
26
+ if (!graph.manifestsByKey.has(dependency)) {
27
+ issues.push(
28
+ toIssue(
29
+ "PACK_DEPENDENCY_MISSING",
30
+ `Pack "${manifest.key}" depends on unknown pack "${dependency}".`,
31
+ `dependencies:${manifest.key}`
32
+ )
33
+ );
34
+ return;
35
+ }
36
+ const dependencyDependents = graph.adjacency.get(dependency) ?? [];
37
+ dependencyDependents.push(manifest.key);
38
+ graph.adjacency.set(dependency, dependencyDependents);
39
+ graph.indegree.set(manifest.key, (graph.indegree.get(manifest.key) ?? 0) + 1);
40
+ }
41
+ function linkPackDependencies(manifests, graph, issues) {
42
+ for (const manifest of manifests) {
43
+ for (const dependency of manifest.dependencies) {
44
+ linkPackDependency(manifest, dependency, graph, issues);
45
+ }
46
+ }
47
+ }
48
+ function topologicalPackOrder(graph) {
49
+ const queue = [...graph.indegree.entries()].filter(([, value]) => value === 0).map(([packKey]) => packKey).sort();
50
+ const orderedPackKeys = [];
51
+ while (queue.length > 0) {
52
+ const nextKey = queue.shift();
53
+ if (!nextKey) {
54
+ break;
55
+ }
56
+ orderedPackKeys.push(nextKey);
57
+ const dependents = graph.adjacency.get(nextKey) ?? [];
58
+ for (const dependent of dependents) {
59
+ const updated = (graph.indegree.get(dependent) ?? 0) - 1;
60
+ graph.indegree.set(dependent, updated);
61
+ if (updated === 0) {
62
+ queue.push(dependent);
63
+ }
64
+ }
65
+ queue.sort();
66
+ }
67
+ return orderedPackKeys;
68
+ }
69
+ function recordUnresolvedDependencyCycles(orderedPackKeys, graph, issues) {
70
+ if (orderedPackKeys.length === graph.manifestsByKey.size) {
71
+ return;
72
+ }
73
+ const unresolved = [...graph.indegree.entries()].filter(([, value]) => value > 0).map(([key]) => key).sort();
74
+ issues.push(
75
+ toIssue(
76
+ "PACK_DEPENDENCY_CYCLE",
77
+ `Dependency graph is not acyclic; unresolved packs: ${unresolved.join(", ")}`,
78
+ "dependencies"
79
+ )
80
+ );
81
+ }
15
82
  function walkDependencyClosure(manifestKey, manifestsByKey, path, closure, issues) {
16
83
  const manifest = manifestsByKey.get(manifestKey);
17
84
  if (!manifest) {
@@ -52,63 +119,8 @@ function walkDependencyClosure(manifestKey, manifestsByKey, path, closure, issue
52
119
  );
53
120
  }
54
121
  }
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 = {};
122
+ function dependencyClosureByPack(manifests, manifestsByKey, issues) {
123
+ const dependencyClosure = {};
112
124
  for (const manifest of manifests) {
113
125
  const closure = /* @__PURE__ */ new Set();
114
126
  walkDependencyClosure(
@@ -118,11 +130,23 @@ function resolvePackDependencyGraph(manifests) {
118
130
  closure,
119
131
  issues
120
132
  );
121
- dependencyClosureByPack[manifest.key] = [...closure].sort();
133
+ dependencyClosure[manifest.key] = [...closure].sort();
122
134
  }
135
+ return dependencyClosure;
136
+ }
137
+ function resolvePackDependencyGraph(manifests) {
138
+ const issues = [];
139
+ const graph = initializeDependencyGraph(manifests);
140
+ linkPackDependencies(manifests, graph, issues);
141
+ const orderedPackKeys = topologicalPackOrder(graph);
142
+ recordUnresolvedDependencyCycles(orderedPackKeys, graph, issues);
123
143
  return {
124
144
  orderedPackKeys,
125
- dependencyClosureByPack,
145
+ dependencyClosureByPack: dependencyClosureByPack(
146
+ manifests,
147
+ graph.manifestsByKey,
148
+ issues
149
+ ),
126
150
  issues,
127
151
  valid: issues.every((issue) => issue.severity !== "error")
128
152
  };
@@ -326,12 +350,7 @@ var dealsV1Manifest = defineAppPackManifest({
326
350
  lifecycle: "beta",
327
351
  category: "domain",
328
352
  description: "Deal diligence application using shared reasoning graph primitives with deal-calibrated workflows.",
329
- dependencies: [
330
- "chat-v1",
331
- "documents-v1",
332
- "news-v1",
333
- "decisions-v1"
334
- ],
353
+ dependencies: ["chat-v1", "documents-v1", "news-v1", "decisions-v1"],
335
354
  capabilityFlags: [
336
355
  "deal.lifecycle",
337
356
  "diligence.workflow",